その辺にいるITインフラ屋さん

気が向いた時に適当な記事を書いたりする個人の備忘録です。個人で開発しているアプリの事やインフラについてなどの記事を書いたりすると思います。更新頻度は少なめ

KubernetesでAmbassadorを使ってhttps通信をさせる

過去の記事でGKEを使ってnginxを動かしてみましたが、httpsの通信は出来ない状態でした。nginx自体にLet's Encryptの証明書を設定してhttps通信をさせる事も出来ますが、nginx自体を自前で管理するのはしたくないです。AmbassadorというAPI Gatewayとして動作させるものがあるので利用してみました。



Ambassadorの設定をする

基本的にDeploying Ambassador to Kubernetesと同じです。下記はGKEで利用した場合の流れになります。

  • clusterrolebindingを設定する

    • kubectl create clusterrolebinding my-cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud info --format="value(config.account)")
  • ambassadorをローカルにダウンロードしてデプロイする

    • curl -O https://www.getambassador.io/yaml/ambassador/ambassador-rbac.yaml
    • kubectl apply -f ambassador-rbac.yaml
  • ambassadorのServiceを作成する
    • ambassador-service.yamlを作成する
    • kubectl apply -f ambassador-service.yamlでデプロイする
# ambassador-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ambassador
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
   - port: 80
     targetPort: 8080
  selector:
    service: ambassador
  • nginxのdeploymentを起動させる (過去の記事参考)
  • nginxのserviceにAmbassadorのannotationsを追加する
apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v1
      kind:  Mapping
      name:  nginx_mapping
      prefix: /nginx/
      service: nginx
spec:
  selector:
    name: nginx
  ports:
  - port: 80
    name: http-nginx
    targetPort: http-nginx-port
  • kubectl get svc ambassador で EXTERNAL-IPを確認する
mayu-mbp-2:kubernetes mayu$ kubectl get svc ambassador
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP    PORT(S)                      AGE
ambassador   LoadBalancer   *****         *****     80:30294/TCP,443:32689/TCP   178m
  • <EXTERNAL-IP>/nginx/にブラウザで接続するとnginxの初期画面が表示される。 f:id:mayuki123:20190602174439p:plain

cert-managerを使って証明書を準備する

基本的にはcert-managerAmbassadorのドキュメントを参考にしています。cert-managerは Let's EncryptACMEプロトコルを利用して証明書を自動更新する事が出来ます。

事前準備

  • namespace cert-managerを作成する
    • kubectl create namespace cert-manager
  • resource validationの除外設定をしておきます。
  • kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
  • cert-managerの設定をダウンロードしてデプロイします。
    • curl -O https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/cert-manager.yaml
    • kubectl apply -f cert-manager.yaml

証明書の作成

issuerCertificate リソースを作成する必要があります。Issuerはクライアント証明書でCertificateはサーバ証明書の発行を行います。ネームスペースに閉じた証明書を利用する場合は kind: Issuerクラスタ全体で利用する場合は kind: ClusterIssuerで作成をしてください。この記事ではClusterIssuerで進めます。

  • ClusterIssuer リソースを作成する
    • kubectl apply -f clusterIssuer.yaml
# clusterIssuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: <mail-address>
    privateKeySecretRef:
      name: letsencrypt-staging
    http01: {}
  • Certificateリソースを作成する
    • kubectl apply -f certificate.yaml
# certificate.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: kubernetes-certificate
  namespace: default
spec:
  secretName: kubernetes-cert-secret
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer
  dnsNames:
  - <your_domain>
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - <your_domain>

HTTP-01 Challengeの設定

ACME認証では HTTPかDNSを利用するかの二種類があります。
(Ambassadorのドキュメント)

  • cert-managerのpodから acme-http-domainacme-http-tokenを取得する
    • kubectl logs cert-manager-69568fb89d-76zm6 -n cert-manager | grep acme-http
    • 下記のようなログが出力されます
I0608 21:19:28.249101       1 ingress.go:49] 
Looking up Ingresses for selector certmanager.k8s.io/acme-http-domain=161156668,certmanager.k8s.io/acme-http-token=1100680922
  • acme-challenge-service リソースを作成します。
    • 先ほど取得したacme-http-domainacme-http-tokenを書き換えます。
apiVersion: v1
kind: Service
metadata:
  name: acme-challenge-service
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v1
      kind: Mapping
      name: acme-challenge-mapping
      prefix: /.well-known/acme-challenge
      rewrite: ""
      service: acme-challenge-service
spec:
  ports:
  - port: 80
    targetPort: 8089
  selector:
    certmanager.k8s.io/acme-http-domain: "161156668"  #rewrite
    certmanager.k8s.io/acme-http-token: "1100680922"  #rewrite

nginxにhttpsで通信出来てるかの確認

  • kubectl get svc ambassador で EXTERNAL-IPを確認して設定したドメインに登録する
  • <ドメイン名>/nginx/にブラウザで接続するとhttps通信がされるようになりました。
    • httpで接続した際はhttpsにリダイレクトされます。

f:id:mayuki123:20190609064026p:plain


一通りやってみましたが、実施すべき事が多いですね。 消したり作ったりする場合は、クラスタ構築のパイプラインを作った方が良さそう。