kubernetes + kops + externalDNS 정리 두번째
첫번째 내용은 여기서 확인 가능합니다.
여기서는 Route53 연동을 위한 ExternalDNS를 알아봅니다.
kubernetes + kops with ExternalDNS
이제 service expose 가 필요한 Services 들을 위해 Route53 연동을 시작해봅시다.
Install ExternalDNS
external-dns/aws.md at master · kubernetes-incubator/external-dns · GitHub
위 링크에 가면 ExternalDNS on AWS 에 대한 설명이 나옵니다.
여기서 중요하게 집고 넘어가야할 부분이 IAM 설정입니다.
저는 처음에 kops IAM 설정에 위의 설정들이 다 들어가 있기 때문에 괜찮을 거라고 생각하고 넘어갔다가 상당히 고생했습니다.
위 링크에서 설명하고 있는 IAM은 k8s의 node role 에 대한 설정입니다.
kops 로 클러스터를 구성하면, master node와 nodes 들의 role들이 별도로 관리가. 됩니다.
아래에서 IAM permission for nodes 를 설정 하겠습니다.
Edit Cluster
kops 를 통해 cluster 에 ExternalDNS 사용을 위한 설정을 추가해줍니다.
kops edit cluster $NAME
위 명령 실행 시 vim 화면이 뜹니다.
내용을 살펴보면 cluster 설정에 대한 yaml 파일 입니다.
Route53 설정을 위해 아래 내용을 하단에 추가해줍니다.
additionalPolicies:
node: |
[
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
위 내용은 node role 에 추가로 IAM policy 설정을 해준다는 의미입니다.
node 이외에도 master, bastion이 있습니다.
관련링크 입니다.
kops/iam_roles.md at master · kubernetes/kops · GitHub
이제 cluster 에 변경사항을 적용해줍니다.
kops update cluster --yes $NAME
이제 AWS console 에서 IAM 의 Role 에서 추가된 Policy 를 확인 하실 수 있습니다.
ExternalDNS on AWS
이제 어플을 배포 해보겠습니다.
배포하기전에 앞에 해야할 일이 ExternalDNS 를 kubernetes 에 생성하는 것입니다.
ExternalDNS 생성
external-dns/aws.md at master · kubernetes-incubator/external-dns · GitHub
위 링크에 있는 external-dns
example 을 사용하겠습니다.
RBAC enabled 된 example 입니다.
external-dns.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:v0.5.0
args:
- --source=service
- --source=ingress
- --domain-filter=k8s.example.com. # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
저장 후에 생성합니다.
kubectl create -f external-dns.yaml
Output:
serviceaccount "external-dns" created
clusterrole.rbac.authorization.k8s.io "external-dns" created
clusterrolebinding.rbac.authorization.k8s.io "external-dns-viewer" created
deployment.extensions "external-dns" create
Pod가 잘 실행 되었는지 확인
kubectl get po
Output
9to5-macbook:~/projects/k8s ktg$ kubectl get po
NAME READY STATUS RESTARTS AGE
curl-545bbf5f9c-rlpwb 1/1 Running 1 6d
external-dns-75d57587fc-dkk8s 1/1 Running 0 43s
hello-go-6db785ccbd-94vdh 1/1 Running 0 6d
nginx-proxy-7b775767b6-fngcz 1/1 Running 0 6d
ExternalDNS Pod 의 로그 확인
kubectl logs -f $(kubectl get po -l app=external-dns -o name)
Output:
9to5-macbook:~/projects/k8s ktg$ kubectl logs -f $(kubectl get po -l app=external-dns -o name)
time="2018-05-17T09:18:45Z" level=info msg="config: {Master: KubeConfig: Sources:[service ingress] Namespace: AnnotationFilter: FQDNTemplate: CombineFQDNAndAnnotation:false Compatibilit$
: PublishInternal:false Provider:aws GoogleProject: DomainFilter:[k8stest.example.com.] ZoneIDFilter:[] AWSZoneType:public AWSAssumeRole: AzureConfigFile:/etc/kubernetes/azure.json AzureRe
sourceGroup: CloudflareProxied:false InfobloxGridHost: InfobloxWapiPort:443 InfobloxWapiUsername:admin InfobloxWapiPassword: InfobloxWapiVersion:2.3.1 InfobloxSSLVerify:true DynCustomerN
ame: DynUsername: DynPassword: DynMinTTLSeconds:0 InMemoryZones:[] PDNSServer:http://localhost:8081 PDNSAPIKey: Policy:sync Registry:txt TXTOwnerID:default TXTPrefix: Interval:1m0s Once:
false DryRun:false LogFormat:text MetricsAddress::7979 LogLevel:info}"
time="2018-05-17T09:18:45Z" level=info msg="Connected to cluster at https://100.64.0.1:443"
time="2018-05-17T09:18:46Z" level=info msg="All records are already up to date"
...
정상 동작을 확인했습니다.
이제 실제 우리가 서비스에 사용할 app 을 배포해봅시다.
여기서 예제는 nginx
입니다.
NGINX 배포
nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: nginx.k8s.example.com.
spec:
type: LoadBalancer
ports:
- port: 80
name: http
targetPort: 80
selector:
app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
name: http
Deploy and Service 생성
9to5-macbook:~/projects/k8s ktg$ kubectl create -f example/nginx.yaml
service "nginx" created
deployment.extensions "nginx" created
Service nginx
정보 확인
9to5-macbook:~/projects/k8s ktg$ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: <none>
Annotations: external-dns.alpha.kubernetes.io/hostname=nginx.k8s.example.com.
Selector: app=nginx
Type: LoadBalancer
IP: 100.68.183.89
LoadBalancer Ingress: af2addc7959b811e888e41234567890-1234567890.us-east-1.elb.amazonaws.com
Port: http 80/TCP
TargetPort: 80/TCP
NodePort: http 31243/TCP
Endpoints: 100.96.2.16:80
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 1m service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 1m service-controller Ensured load balancer
Load Balancer url test
curl af2addc7959b811e888e41234567890-1234567890.us-east-1.elb.amazonaws.com
ExternalDNS Pod 의 로그 다시 확인
kubectl logs -f $(kubectl get po -l app=external-dns -o name)
Output:
...
time="2018-05-17T09:59:49Z" level=info msg="Desired change: CREATE nginx.k8s.example.com A"
time="2018-05-17T09:59:49Z" level=info msg="Desired change: CREATE nginx.k8s.example.com TXT"
time="2018-05-17T09:59:49Z" level=info msg="Record in zone k8s.example.com. were successfully updated"
...
로그에서 위의 메시지를 찾으면 정상적으로 Route53 에 A record가 생성 되었습니다.
잠시 후에 해당 url
에 request 를 보내봅니다.
curl nginx.k8s.example.com
Load balancer url 에 request 를 보냈을 때와 같은 결과가 나온다면 정상적으로 kubernetes cluster 설정이 완료된 것입니다.