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
Justo, vamos seguir em frente!
Etapa 2: expor vários serviços em um servidor NGINX
O NGINX é um proxy reverso, na medida em que proxies uma solicitação enviando-a para uma origem especificada, busca a resposta e a envia de volta ao cliente. Voltando ao ponto em que os nomes de serviço estão acessíveis a outros pods em um cluster, podemos definir uma configuração do NGINX para algo parecido com isto.
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;
}
}
Observe como podemos fazer referência a hosts de origem como web:3000
e 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
… e pronto! Direita? Na minha experiência, inicialmente eu pensava assim. o LoadBalancer
fornece um IP acessível externamente. Você pode confirmar executando kubectl get svc
e com certeza você encontrará um nome de host listado no EXTERNAL-IP
coluna. Supondo que você adquiriu um domínio de um provedor que oferece uma interface para gerenciar configurações de DNS, você pode simplesmente adicionar esse URL como um CNAME
e você é bom, certo? Bem, meio … mas não tanto.
Os Kubernetes Pods são considerados entidades relativamente efêmeras (e não duráveis). Saiba mais sobre isso em “Ciclo de vida do pod – Kubernetes“. Dito isso, sempre que uma alteração significativa for feita no ciclo de vida de um serviço, no nosso caso, o aplicativo NGINX, teremos um endereço IP diferente que, por sua vez, causará um tempo de inatividade significativo em nosso aplicativo, o que anula o objetivo principal de Kubernetes – para ajudar a estabelecer um aplicativo “altamente disponível”. Ok, não entre em pânico – vamos resolver isso 😬
Etapa 3: Criar um serviço DNS externo para apontar dinamicamente o NGINX
Na etapa anterior, com nossa LoadBalancer
especificação juntamente com EKS, na verdade, criamos um Balanceador de carga elástico (para melhor ou pior). Nesta seção, criaremos um serviço DNS que aponta nosso balanceador de carga via “registro ALIAS”. Esse registro do ALIAS é essencialmente dinâmico, pois um novo é criado sempre que nosso serviço é alterado. A estabilidade é estabelecida nos registros do servidor de nomes.
O tl; dr para a porção restante é simplesmente seguir o documentação para usar ExternalDNS com Route 53. A rota 53 é “serviço da web DNS (Sistema de nomes de domínio) na nuvem“. Abaixo estavam algumas coisas que eu tinha que fazer que não eram óbvias na documentação. Agarre-se aos seus cavalos, isso fica um pouco ruim.
eksctl utils associate-iam-oidc-provider --cluster=your-cluster-name
poreksctl
documentação de contas de serviço.- Ao criar o documento de política do IAM de acordo com o Documentação ExternalDNS, Na verdade, tive que fazer isso via CLI vs online na minha conta. Eu continuei recebendo este erro:
WebIdentityErr: failed to retrieve credentialsncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentityntstatus code: 403
. Quando criei a política via CLI, o problema foi resolvido. Abaixo está o comando completo que você deve ser capaz de copiar e executar literalmente se tiver o CLI da AWS instalado.
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":["*"]}]}'
- Use a saída de ARN da política acima para criar uma função do IAM vinculada à conta de serviço ExternalDNS com um comando que será semelhante a
eksctl create iamserviceaccount --cluster=your-cluster-name --name=external-dns --namespace=default --attach-policy-arn=arn:aws:iam::123456789:policy/AllowExternalDNSUpdates
. - Agora devemos ter um novo papel do acima exposto que podemos ver no Console do IAM que terá um nome de algo como
eksctl-foo-addon-iamserviceaccount-Role1-abcdefg
. Clique no papel da lista e, na parte superior da tela seguinte, anote o “Role ARN” como algo comoarn:aws:iam::123456789:role/eksctl-foo-addon-iamserviceaccount-Role1-abcdefg
. - Segue estes passos para criar uma “zona hospedada” na Rota 53.
- Você pode confirmar as coisas no Console Route 53.
- Se o seu provedor de domínio permitir que você gerencie as configurações de DNS, adicione os 4 registros do servidor de nomes na saída do comando que você executou para criar uma “zona hospedada”.
- Implante o ExternalDNS seguindo As instruções. Depois, você pode ajustar os logs com
kubectl logs -f name-of-external-dns-pod
. Você deve ver uma linha como esta no final:time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"
Calma né ?! Ok, talvez não … mas pelo menos você não precisava entender tudo sozinho 😓 Pode haver algumas lacunas acima, mas espero que isso ajude você a guiar seu processo.
Conclusão
Embora esta postagem possa ter algumas áreas cinzentas, se ajudar a estabelecer a resolução DNS dinâmica como parte de um aplicativo altamente disponível, você terá algo realmente especial 🙏
Adicione comentários se eu puder ajudar a esclarecer alguma coisa ou corrigir minha terminologia!