最近社内でもっぱらk8sを触っているなかで社内で雑にコンテナ立てるだけで https://example.com
とか公開できるようにした。
external-dns
まずは、名前解決ができるようにするのと、cert-managerを利用してLet’sEncryptでワイルドカード証明書を払い出すために、Route53を利用するためにexternal-dnsをたてた。
マニフェストは雑にこんな感じ。
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"] - apiGroups: [""] resources: ["nodes"] verbs: ["list","watch"] --- 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: example-system --- apiVersion: apps/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.14 args: - --source=service - --source=ingress - --domain-filter=<your domain> - --provider=aws - --policy=upsert-only - --registry=txt - --txt-owner-id=<your id> env: - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: external-dns key: aws_access_key_id - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: external-dns key: aws_secret_access_key
Route53にアクセスするための権限が必要なので、ユーザーを払い出して、下記の権限を与えておいてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "route53:ChangeResourceRecordSets", "Resource": [ "arn:aws:route53:::hostedzone/*" ] }, { "Effect": "Allow", "Action": "route53:ChangeResourceRecordSets", "Resource": [ "arn:aws:route53:::hostedzone/*" ] }, { "Effect": "Allow", "Action": "route53:GetChange", "Resource": [ "arn:aws:route53:::change/*" ] }, { "Effect": "Allow", "Action": [ "route53:ListHostedZones", "route53:ListHostedZonesByName", "route53:ListResourceRecordSets" ], "Resource": [ "*" ] } ] }
cert-manager
cert-managerはhelmを利用しました。こんな感じでシュッと入ります。
$ helm install \ --name cert-manager \ --namespace <your-namespace> \ stable/cert-manager
次にcert-managerが利用するCRDをデプロイします。これはGithubの最新パージョンを利用します。
$ kubectl -n <your-namespace> apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/00-crds.yaml
最後に、証明書の設定をCRDを利用して行います。
apiVersion: certmanager.k8s.io/v1alpha1 kind: ClusterIssuer metadata: name: letsencrypt spec: acme: email: admin@example.com # staging:https://acme-staging-v02.api.letsencrypt.org/directory server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-private-key dns01: providers: - name: route53 route53: accessKeyID: xxxxxxxxxxxxxxxxxxxxxxxxx region: ap-northeast-1 secretAccessKeySecretRef: name: external-dns key: aws_secret_access_key
実際に証明書を発行するには下記のリソースをapplyしてください。
apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: wildcard-example.com spec: acme: config: - dns01: provider: route53 domains: - '*.example.com' commonName: '*.example.com' issuerRef: kind: ClusterIssuer name: letsencrypt secretName: cert-wildcard-example
発行状況は下記のコマンドで確認可能です。
$ kubectl describe cert wildcard-example.com
Ingressから利用する
Ingressのインストールは このあたりが参考になります。Ingressをデプロイしたら、あとはこのように利用できます。
--- apiVersion: apps/v1beta1 kind: Deployment metadata: name: hello-world-deployment spec: replicas: 1 template: metadata: labels: app: hello-world spec: containers: - image: "strm/helloworld-http" imagePullPolicy: Always name: hello-world-container ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: hello-world-svc annotations: external-dns.alpha.kubernetes.io/hostname: example.com spec: type: ClusterIP ports: - port: 8080 protocol: TCP targetPort: 80 selector: app: hello-world --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: hello-world-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.org/ssl-services: "hello-world-svc" ingress.kubernetes.io/ssl-redirect: "false" spec: tls: - hosts: - example.com secretName: cert-wildcard-example rules: - host: example.com http: paths: - path: / backend: serviceName: hello-world-svc servicePort: 8080
ペパボのように多くの商材がある会社では、このようにIngressを作っておくだけで簡単にサービスを公開できるので、社内システムなどすぐにレバレッジを効かせることができます。しかもhttpsな通信でセキュアだしお得。
最後に
最近はこういうことを全社でバーーーンとやれるように @r_takaishi とあれこれやっている。これからいよいよ既存サービスやOpenStack、AWSとk8sを組み合わせて移行したり、新しいものを作っていくフェーズなので誰か一緒にやりましょう。