🎉

さくらのクラウドに構築したKuberentes上でCert managerを利用する

2020/12/18に公開

概要

さくらのクラウド上に構築したKubernetesで最新版のCert managerが利用可能となりました🎉

そこで今回はCert managerと対応プラグインをインストールし証明書の取得及びTLS通信の実現までを解説します。

Cert managerには未対応DNSプロバイダ用の拡張インターフェースがwebhookとして用意されており、その仕組みを用いてさくらのクラウド上でもCert managerの利用と可能にしています。

https://cert-manager.io/docs/concepts/webhook/

Cert managerの拡張方法に関しては以下の記事で実際のコードと共に解説しています。

https://zenn.dev/0n1shi/articles/cf583802e0c119

インストール

インストール手順は以下で参照が可能です。

https://sakura-internet.github.io/cert-manager-sacloud-webhook-helm-chart/

ここでは上記の手順に沿って解説をしていきます。

Cert menager

まず最初にCert managerをインストールします。

  • 名前空間の作成
$ kubectl create namespace cert-manager
  • Helmリポジトリの追加
$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
  • カスタムリソースの作成
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.4/cert-manager.crds.yaml
  • Cert managerのインストール
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.0.4

これでCert managerのインストールは以上になります。

Webhookプラグイン

次にWebhookプラグインをインストールしてCert managerをさくらのクラウド上で利用可能にします。

以下ではチャートのリポジトリを追加しHelmをインストールします。

$ helm repo add cert-manager-sacloud-webhook https://sakura-internet.github.io/cert-manager-sacloud-webhook-helm-chart/
$ helm install cert-manager-sacloud-webhook cert-manager-sacloud-webhook/cert-manager-sacloud-webhook --namespace cert-manager --version v1.0.0

利用

ここから実際に先ほどインストールしたCert manager及びWebhookのプラグインを用いて証明書の発行、NginxでのTLS通信を行います。

先ほどHelmチャートのリポジトリとして追加したページはGithubのリポジトリとして以下で公開されており、examplesディレクトリにあるサンプルマニフェストでここからの動作検証を行います。

https://github.com/sakura-internet/cert-manager-sacloud-webhook-helm-chart

ClusterIssuerの作成

証明書の発行処理をハンドリングするClusterIssuerを作成します。これはグループ名とソルバ名を指定することにより先ほど登録しておいたWebhookプラグインを証明書発行処理のハンドラとして設定します。

ClusterIssuerのサンプルマニフェストはexamples/cert-manager-sacloud-webhook/issuer.yamlで以下のように定義されています。

apiVersion: v1
kind: Secret
metadata:
  name: sakuracloud-api-token-secret
  namespace: cert-manager
type: Opaque
data:
  access-token: <base64 encoded API token> # need to edit
  access-secret: <base64 encoded API token secret> # need to edit

---
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: sacloud-issuer
  namespace: cert-manager
spec:
  acme:
    email: <your email address> # need to edit
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: sacloud-issuer-account-key
    solvers:
      - dns01:
          webhook:
            groupName: sakura.ad.jp
            solverName: saclouddns
            config:
              accessKeySecretRef:
                name: sakuracloud-api-token-secret
                key: access-token
              secretKeySecretRef:
                name: sakuracloud-api-token-secret
                key: access-secret

上記では以下の値を変更する必要があります。

キー
<base64 encoded API token> BASE64エンコードしたAPIトークン
<base64 encoded API token secret> BASE64エンコードしたAPIシークレット
<your email address> 利用するメールアドレス

変更後以下のコマンドでApplyします。

$ kubectl apply -f examples/cert-manager-sacloud-webhook/issuer.yaml

Certificateの作成

次に証明書のデータを保持したシークレットの発行を行うためのCertificateを作成します。Certificateリソースのマニフェストはexamples/cert-manager-sacloud-webhook/certificate.yamlで以下のように定義されています。

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: sacloud-tls
  namespace: default
spec:
  secretName: <secret name> # need to edit
  commonName: "*.<your domain>" # need to edit
  dnsNames:
    - "*.<your domain>" # need to edit
  issuerRef:
    name: sacloud-issuer
    kind: ClusterIssuer

上記では以下の値を変更する必要があります。

キー
<secret name> 証明書のデータを格納するシークレット名
<your domain> ドメイン

変更後以下のコマンドでApplyします。

$ kubectl apply -f examples/cert-manager-sacloud-webhook/certificate.yaml

Certificateのステータスがtrueになると証明書のデータを保持したシークレットが作成されます。

Nginxのデプロイ

先ほどCertificateリソースで作成したシークレットを用いてNginxのTLS通信を行います。

Nginxのマニフェストはexamples/cert-manager-sacloud-webhook/nginx.yamlで以下のように定義されています。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-myservice
  namespace: default
spec:
  tls:
    - hosts:
        - <hostname> # need to edit
      secretName: <secret name> # need to edit
  rules:
    - host: <hostname> # need to edit
      http:
        paths:
          - path: /
            backend:
              serviceName: nginx
              servicePort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx

上記では以下の値を変更する必要があります。

キー
<hostname> 証明書を発行したドメイン配下でのホスト名
<secret name> 証明書のデータを保持したシークレット名

変更後以下のコマンドでApplyします。

$ kubectl apply -f examples/cert-manager-sacloud-webhook/nginx.yaml

上記で指定したホスト名でNginxにアクセス可能で且つLTS通信が行えている場合正常に動作しています。

トラブルシューディング

CertificateリソースのステータスがtrueにならずSecretが作成されない

A. Certificateのリソースのステータスがtrueになるまで数秒から数(2~3)分かかるので気長に待ちましょう。

Discussion