În calitate de creator al Foo, o platformă pentru monitorizarea calității site-ului web, M-am străduit recent într-o migrare către Kubernetes și EKS (un serviciu AWS).
Kubernetes oferă un nivel robust de suport DNS. Din fericire pentru noi, în cadrul unui cluster, putem face referință la pod-uri după numele gazdei, așa cum este definit într-o specificație.
Dar dacă vrem să expunem o aplicație către lumea exterioară ca site web sub un domeniu static? Am crezut că acesta ar fi un caz obișnuit, bine documentat, dar băiatul m-am înșelat.
Să presupunem un serviciu numit
foo
în spațiul de nume Kubernetesbar
. Un pod care rulează în spațiul de numebar
poate căuta acest serviciu făcând pur și simplu o interogare DNS pentrufoo
. Un pod care rulează în spațiul de numequux
poate căuta acest serviciu făcând o interogare DNS pentrufoo.bar
~ DNS pentru servicii și poduri – Kubernetes
Da, este grozav ❤️ Dar acest lucru duce încă la multe mistere nerezolvate. Să facem acest pas la rând, nu ?! Această postare va aborda următoarele elemente.
- Cum se definesc serviciile
- Cum să expuneți mai multe servicii sub un singur server NGINX. Fără schmancy fantezie “Ingress” Necesar ?
- Cum să creați un DNS extern și să vă conectați la un domeniu ați achiziționat prin orice registru calificat, cum ar fi GoDaddy sau Google Domains, de exemplu. Vom folosi Traseul 53 și ExternalDNS să facă ridicarea grea.
Această postare presupune o configurare cu EKS și eksctl
așa cum este documentat în „Începând cu eksctl
“, dar multe dintre conceptele și exemplele din această postare ar putea fi aplicabile într-o varietate de configurații.
Table of Contents
Pasul 1: definiți serviciile
Conectarea aplicațiilor cu serviciile explică modul de expunere a unei aplicații NGINX prin definirea unui Deployment
și Service
. Să mergem mai departe și să creăm 3 aplicații în același mod: o aplicație web orientată către utilizator, un API și un server proxy invers NGINX pentru a expune cele două aplicații sub o singură gazdă.
web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
# etc, etc
web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app: web
spec:
ports:
- name: "3000"
port: 3000
targetPort: 3000
selector:
app: web
api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
# etc, etc
api-service.yaml
apiVersion: v1
kind: Service
metadata:
name: api
labels:
app: api
spec:
ports:
- name: "3000"
port: 3000
targetPort: 3000
selector:
app: api
Destul de corect, să mergem mai departe!
Pasul 2: expuneți mai multe servicii sub un singur server NGINX
NGINX este un proxy invers prin faptul că transmite o solicitare prin trimiterea acesteia către o origine specificată, preia răspunsul și îl trimite înapoi către client.
Revenind la informațiile despre faptul că numele serviciilor sunt accesibile altor pod-uri dintr-un cluster, putem configura o configurație NGINX pentru a arăta așa ceva.
sites-enabled / www.example.com.conf
upstream api {
server api:3000;
}
upstream web {
server web:3000;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://web;
}
location /api {
proxy_pass http://api;
}
}
Rețineți cum putem face referință la gazde de origine cum ar fi web:3000
și api:300
. Niiiice!
nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
# this part will make more sense later
external-dns.alpha.kubernetes.io/hostname: www.example.com
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- name: "80"
port: 80
targetPort: 80
selector:
app: nginx
… și, am terminat! Dreapta? Din experiența mea, inițial așa am crezut. LoadBalancer
oferă un IP accesibil extern. Puteți confirma rularea kubectl get svc
și sigur că veți găsi un nume de gazdă listat în EXTERNAL-IP
coloană.
Presupunând că ați achiziționat un domeniu de la un furnizor care oferă o interfață pentru gestionarea setărilor DNS, puteți adăuga pur și simplu această adresă URL ca CNAME
si esti bun, nu? Ei bine, cam … dar nu atât.
Podurile Kubernetes sunt considerate a fi entități relativ efemere (mai degrabă decât durabile). Găsiți mai multe despre acest lucru în „Ciclul de viață al podului – Kubernetes“.
Cu toate acestea, oricând s-a făcut o schimbare semnificativă în ciclul de viață al unui serviciu, în cazul nostru aplicația NGINX, vom avea o adresă IP diferită, care la rândul său va provoca perioade de nefuncționare semnificative în aplicația noastră, care învinge un scop principal al Kubernetes – pentru a ajuta la stabilirea unei aplicații „extrem de disponibile”.
Bine, nu intra în panică – vom trece prin asta?
Pasul 3: Creați un serviciu DNS extern pentru a puncta dinamic NGINX
În pasul anterior, cu LoadBalancer
spec. împreună cu EKS am creat de fapt un Balansator de sarcină elastic (pentru mai bine sau mai rău).
În această secțiune vom crea un serviciu DNS care ne indică echilibrarea sarcinii prin „înregistrarea ALIAS”. Această înregistrare ALIAS este în esență dinamică prin aceea că se creează una nouă de fiecare dată când serviciul nostru se schimbă. Stabilitatea este stabilită în înregistrările serverului de nume.
Tl; dr pentru porțiunea rămasă este pur și simplu urmați documentație pentru utilizarea ExternalDNS cu Route 53. Traseul 53 este „serviciu web Cloud Domain Name System (DNS)“.
Mai jos erau lucruri pe care trebuia să le fac, care nu erau evidente din documentație. Ține-te de caii tăi, acest lucru devine puțin scrappy.
-
eksctl utils associate-iam-oidc-provider --cluster=your-cluster-name
peeksctl
documentația conturilor de servicii. - La crearea documentului de politică IAM în conformitate cu Documentație ExternalDNS, De fapt, a trebuit să o fac prin CLI vs online în contul meu. Am continuat să primesc această eroare:
WebIdentityErr: failed to retrieve credentialsncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentityntstatus code: 403
. Când am creat politica prin CLI, problema a dispărut. Mai jos este comanda completă pe care ar trebui să o puteți copia literalmente și să o executați dacă aveți AWS CLI instalat.
aws iam create-policy
--policy-name AllowExternalDNSUpdates
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["route53:ChangeResourceRecordSets"],"Resource":["arn:aws:route53:::hostedzone/*"]},{"Effect":"Allow","Action":["route53:ListHostedZones","route53:ListResourceRecordSets"],"Resource":["*"]}]}'
- Utilizați politica de ieșire ARN de mai sus pentru a crea un rol IAM legat de contul de serviciu ExternalDNS cu o comandă care va arăta ceva de genul
eksctl create iamserviceaccount --cluster=your-cluster-name --name=external-dns --namespace=default --attach-policy-arn=arn:aws:iam::123456789:policy/AllowExternalDNSUpdates
. - Acum ar trebui să avem un nou rol din cele de mai sus, pe care îl putem vedea în Consola IAM care va avea un nume de ceva de genul
eksctl-foo-addon-iamserviceaccount-Role1-abcdefg
. Faceți clic pe rolul din listă și în partea de sus a ecranului următor notați „ROL ARN” ca ceva de genularn:aws:iam::123456789:role/eksctl-foo-addon-iamserviceaccount-Role1-abcdefg
. - Urma acești pași pentru a crea o „zonă găzduită” în Traseul 53.
- Puteți confirma lucrurile în Consola Route 53.
- Dacă furnizorul dvs. de domeniu vă permite să gestionați setările DNS, adăugați cele 4 înregistrări ale serverului de nume din ieșirea comenzii pe care ați executat-o pentru a crea o „zonă găzduită”.
- Implementați ExternalDNS urmând instructiunile. Apoi, puteți coada buștenii cu
kubectl logs -f name-of-external-dns-pod
. Ar trebui să vedeți o linie de genul acesta la sfârșit:time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"
Ușor, nu ?! Bine, poate nu … dar cel puțin nu a trebuit să-ți dai seama de toate singur? Ar putea exista unele lacune mai sus, dar sperăm că vă ajută să vă ghidați în procesul dvs.
Concluzie
Deși această postare poate avea unele zone gri, dacă vă ajută să stabiliți rezoluția DNS dinamică ca parte a unei aplicații extrem de disponibile, aveți ceva cu adevărat special?
Vă rugăm să adăugați comentarii dacă vă pot ajuta să clarific ceva sau să corectez terminologia mea!