LoginSignup
3
3

More than 3 years have passed since last update.

Azure Kubernetes Service(AKS)にLet's EncryptのSSL証明書を入れる

Posted at

元ネタ

準備

注意

  • 静的パブリック IP アドレスは、お金がかかる
  • AKS クラスターを削除すると、静的パブリック IP アドレスも解放されて消えてしまうので注意。

静的IPアドレスを取得する

  • AKS クラスターのリソース グループ名を取得

    • AKS_NODE_RES_GROUP=`az aks show --resource-group $AKS_RES_GROUP --name $AKS_CLUSTER_NAME --query nodeResourceGroup -o tsv`
  • 静的パブリック IP アドレスを作成

    • az network public-ip create --resource-group $AKS_NODE_RES_GROUP --name myAKSPublicIP --allocation-method static
      • 上記では名前をmyAKSPublicIPにしているが、適宜変更。
  • 作成した静的パブリック IP アドレスを確認

    • az network public-ip list --query [].ipAddress
      • 複数ある場合は、後々の設定でハマるので、ポータルから「パブリック IP アドレス 」で探して削除する。
    • PUBLIC_IP_ADDRESS=`az network public-ip list --query [].ipAddress -o tsv`

nginx-ingress をIPアドレス指定でインストール

  • インストール
    • namespaceをkube-systemにしている。サンプルによってはkube-publicにしている場合もあるので注意。
helm install stable/nginx-ingress \
    --namespace kube-system \
    --set controller.service.loadBalancerIP=$PUBLIC_IP_ADDRESS
  • パブリックIPを確認
    • kubectl get service -l app=nginx-ingress --namespace kube-system
      • EXTERNAL-IP<pending>の場合は、少し待つ。
NAME                                             TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
excited-starfish-nginx-ingress-controller        LoadBalancer   10.0.14.43     40.115.xxx.xxx   80:30202/TCP,443:31925/TCP   1m
excited-starfish-nginx-ingress-default-backend   ClusterIP      10.0.121.158   <none>          80/TCP                       1m
  • ブラウザで、上記の40.115.xxx.xxxにアクセスする
    • default backend - 404のように、デフォルトの404ページが表示される(起動に数分かかるので待つ)

DNS上の名前を決めて、設定

  • DNSNAME="my-aks-ingress-test123"
  • PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$PUBLIC_IP_ADDRESS')].[id]" --output tsv)
  • az network public-ip update --ids $PUBLICIPID --dns-name $DNSNAME

  • これでFQDNを使ってアクセスできるようになったので、ブラウザで開いて確認する

cert-manager をインストール

  • Let's Encrypt 証明書を自動的に作成および管理する機能を提供する cert-manager を入れる
    • 0.7.2が出ているので、0.6ではなく0.7を使う。
      • kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/00-crds.yaml
    • cert-manager用に名前空間を作成(kube-systemではなくcert-managerという名前空間に入れる)
      • kubectl create namespace cert-manager
      • kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
        • disable-validation=trueを付けないと発行者が不明になって証明書が作成されない??
    • helmを使ってインストールする(GitHubのcert-managerのページ を見ると0.7.2が最新なのでバージョン指定する際は確認する)
      • helm repo add jetstack https://charts.jetstack.io
      • helm repo update
helm install \
  --name cert-manager \
  --namespace cert-manager \
  --version v0.7.2 \
  jetstack/cert-manager
  • 本番環境の場合は、--set ingressShim.extraArgs='{--default-issuer-name=letsencrypt-prod,--default-issuer-kind=ClusterIssuer}'も付ける。
    • 下記の例では名前空間kube-systemに入れている
    • webhook.enables=false を書かないと証明書が発行されないという情報もあるので追記
    • stable/cert-managerだとうまくいかなかったのでjetstack/cert-managerを使った
  • 上記で証明書を入れられたので、下記は参考。
helm install jetstack/cert-manager \
  --name cert-manager \
  --namespace kube-system \
  --set ingressShim.defaultIssuerName=letsencrypt-prod \
  --set ingressShim.defaultIssuerKind=ClusterIssuer \
  --set webhook.enabled=false
  • 入れ間違えたら、helm delete --purge cert-managerで消して入れ直し。

    • Error: customresourcedefinitions.apiextensions.k8s.io "certificates.certmanager.k8s.io" already exists の場合は、kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/00-crds.yaml で消す
  • これだけで(信頼されない)証明書が発行されるので、ブラウザでHTTPSで接続して確認する

CA クラスター発行者を作成

  • cluster-issuer.yamlファイルを以下の内容で作成
  • emailを、実際のメールアドレスに変更する
  • テスト用なので、stagingを使用する。本番環境ではletsencrypt-prodhttps://acme-v02.api.letsencrypt.org/directory を使用する
    • サーバはv01ではなくv02を使わないと、ずっとIssuer letsencrypt-staging not readyのままで原因が分かりづらい。
      • kubectl describe clusterissuer letsencrypt-stagingkubectl describe clusterissuer letsencrypt-prodで状況を確認。
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  #name: letsencrypt-prod
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    #server: https://acme-v02.api.letsencrypt.org/directory
    email: user@example.com
    privateKeySecretRef:
      name: letsencrypt-staging
      #name: letsencrypt-prod
    http01: {}
  • kubectl apply -f cluster-issuer.yaml で適用
    • Error from server (InternalError): error when creating "cluster-issuer.yaml": Internal error occurred: failed calling admission webhook "clusterissuers.admission.certmanager.k8s.io": the server is currently unable to handle the request と表示されたら、しばらく待ってもう一度行う

デモ アプリを入れる

  • デフォルトの404ページで動作確認しようとしてはまったので、デモ アプリを入れる
    • helm repo add azure-samples https://azure-samples.github.io/helm-charts/
    • helm install azure-samples/aks-helloworld --namespace ingress-basic
    • helm list --namespace ingress-basic
    • helm install azure-samples/aks-helloworld --namespace ingress-basic --set title="AKS Ingress Demo" --set serviceName="ingress-demo"
    • helm list --namespace ingress-basic

イングレス ルートを作成

  • hello-world-ingress.yaml を以下で作成
  • hostshostは自分のホスト名に変更する
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-world-ingress
  namespace: ingress-basic
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - my-aks-ingress-test123.japaneast.cloudapp.azure.com
    secretName: tls-secret
  rules:
  - host: my-aks-ingress-test123.japaneast.cloudapp.azure.com
    http:
      paths:
      - path: /
        backend:
          serviceName: aks-helloworld
          servicePort: 80
      - path: /hello-world-two
        backend:
          serviceName: ingress-demo
          servicePort: 80
  • kubectl apply -f hello-world-ingress.yamlで適用

証明書の確認

  • 上記で自動的に要求される

    • kubectl describe certificate tls-secret --namespace ingress-basic
    • kubectl describe certificate tls-secret
    • kubectl describe certificate で状況確認
    • kubectl describe order
    • ずっとIssuer letsencrypt-prod not readyのままの場合、kubectl describe clusterissuer letsencrypt-stagingkubectl describe clusterissuer letsencrypt-prodで状況を確認。
      • 引数はcluster-issuerではなくclusterissuerなので注意
  • kubectl describe clusterissuer letsencrypt-prod で状態が表示できる

(略)
Status:
  Acme:
    Uri:  https://acme-v02.api.letsencrypt.org/acme/acct/56269408
  Conditions:
    Last Transition Time:  2019-05-02T07:29:25Z
    Message:               The ACME account was registered with the ACME server
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
Events:                    <none>
  • kubectl describe certificate tls-secret --namespace ingress-basic で以下のようにイベント詳細が表示できる
(略)
Status:
  Conditions:
    Last Transition Time:  2019-05-02T07:29:51Z
    Message:               Certificate is up to date and has not expired
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2019-07-31T06:29:50Z
Events:
  Type     Reason              Age                    From          Message
  ----     ------              ----                   ----          -------
  Warning  IssuerNotFound      3m44s                  cert-manager  clusterissuer.certmanager.k8s.io "letsencrypt-prod" not found
  Warning  IssuerNotReady      3m28s (x3 over 7m31s)  cert-manager  Issuer letsencrypt-prod not ready
  Normal   Generated           3m27s                  cert-manager  Generated new private key
  Normal   GenerateSelfSigned  3m27s                  cert-manager  Generated temporary self signed certificate
  Normal   OrderCreated        3m27s                  cert-manager  Created Order resource "tls-secret-224255xxxx"
  Normal   OrderComplete       3m1s                   cert-manager  Order "tls-secret-224255xxxx" completed successfully
  Normal   CertIssued          3m1s                   cert-manager  Certificate issued successfully
  • ステータスがCertificate issuance in progress. Temporary certificate issued.の場合は、しばらく待つ。

    • Temporary certificateが発行されてから、本物のcertificateが発行される。という順番なので、ステータスで確認。
  • chromeの開発者ツールのSecurityで見ると、Certificate - valid and trusted
    の下に The connection to this site is using a valid, trusted server certificate issued by 不明な名前.となっている場合がある。対処方法不明。

ブラウザで表示して、証明書の確認

証明書オブジェクトを作成(必要に応じて)

  • certificates.yamlファイルを以下の内容で作成。
  • dnsNamesdomains を前の手順で作成した DNS 名に変更する
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: tls-secret
spec:
  secretName: tls-secret
  dnsNames:
  - my-aks-ingress-test123.japaneast.cloudapp.azure.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - my-aks-ingress-test123.japaneast.cloudapp.azure.com
  issuerRef:
    name: letsencrypt-staging
    #name: letsencrypt-prod
    kind: ClusterIssuer
  • kubectl apply -f certificates.yamlで適用。
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3