<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kubernetes &#8211; SRA OSS Tech Blog</title>
	<atom:link href="https://www.sraoss.co.jp/tech-blog/tag/kubernetes/feed/index.xml" rel="self" type="application/rss+xml" />
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<description>OSS専門の技術ブログ。PostgreSQL、Zabbixを中心に10種類以上のOSSの解説、アップデート情報、運用ヒントを提供。</description>
	<lastBuildDate>Fri, 23 Oct 2026 06:39:34 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2018/07/blog-icon-150x150.png</url>
	<title>Kubernetes &#8211; SRA OSS Tech Blog</title>
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Crunchy Postgres Operator v5 の紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/kubernetes/crunchy-postgres-operator-v5/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Fri, 25 Mar 2022 05:05:52 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Crunchy]]></category>
		<category><![CDATA[Crunchy Data]]></category>
		<category><![CDATA[Operator]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=9360</guid>

					<description><![CDATA[以前の記事 Crunchy Postgres Operatorの紹介 では、バージョン 4 を対象に Crunchy Postgres Operator のインストール方法、主な機能について紹介しました。2021 年にリ ...]]></description>
										<content:encoded><![CDATA[<p>以前の記事 <a href="https://www.sraoss.co.jp/tech-blog/pgsql/crunchy-postgresql-operator/">Crunchy Postgres Operatorの紹介</a> では、バージョン 4 を対象に Crunchy Postgres Operator のインストール方法、主な機能について紹介しました。2021 年にリリースされた バージョン 5 (v5) では、インストールや管理方法が大幅に変更され、より簡単に構築・運用できるようになりました。</p>
<p>本記事では、 Crunchy Postgres Operator (PGO) v5 のインストール方法と主な機能の使い方について紹介します。</p>
<p><span id="more-9360"></span></p>
<p>Operator を使う理由や Crunchy Postgres Operator の概要については以前の記事 <a href="https://www.sraoss.co.jp/tech-blog/pgsql/kubernetes-postgres-operator/">Kubernetes PostgreSQL Operatorの紹介</a>、<a href="https://www.sraoss.co.jp/tech-blog/pgsql/crunchy-postgresql-operator/">Crunchy Postgres Operatorの紹介</a> を参照してください。</p>
<h2>PGO v5 の主な変更点</h2>
<p>以前 v4 で紹介した以下の機能は、v5 でも引き続き利用できます。利用する際の設定方法は v4 までと異なるので、詳しい設定方法については後述します。</p>
<ul>
<li>PostgreSQL HA クラスタのデプロイ・管理</li>
<li>ストリーミングレプリケーション (同期・非同期)</li>
<li>フェイルオーバー</li>
<li>バックアップ</li>
<li>WALアーカイブ</li>
<li>リストア・PITR</li>
<li>アップグレード</li>
<li>コネクションプール</li>
<li>モニタリング</li>
</ul>
<p>PGO v5 における構築・運用の主な変更点は以下の通りです。</p>
<ul>
<li>PGO v5 では、Kustomize または Helm を利用し、PGO をインストールします。v4 までの方法に比べて、より簡単にインストールできるようになりました。</li>
<li>PGO v4 では基本的に pgo クライアントコマンドを利用して各種操作を行っていましたが、PGO v5 では pgo クライアントコマンドが廃止されました。PGO v5では、Kubernetes で一般的によく使われるコマンドラインツール kubectl を利用して PostgreSQL の構築および管理を行います。</li>
<li>PostgreSQL インスタンスは StatefulSet を使用するようになりました。</li>
<li>PGO v4 までは PostgreSQL のマイナーバージョンアップを行うために、「PGO 自身のアップデート」と「PostgreSQL のアップデート」の2段階のアップデートを実行する必要がありましたが、PGO v5 では、PGO のバージョンを更新せず、PostgreSQL のイメージをアップデートするだけでマイナーバージョンアップができるようになりました。</li>
</ul>
<p>その他の改良や変更点についてはPGO 5.0.0 の<a href="https://access.crunchydata.com/documentation/postgres-operator/v5/releases/5.0.0/" target="_blank" rel="noopener">リリースノート</a>を参照してください。</p>
<h2>PGO v5 の動作環境</h2>
<p>本記事執筆時点 (2022 年 3 月) では、以下の環境で動作確認が行われています。</p>
<ul>
<li>Kubernetes 1.19 以降</li>
<li>OpenShift 4.6 以降</li>
<li>Rancher</li>
<li>Google Kubernetes Engine (GKE), Anthos を含む</li>
<li>Amazon EKS</li>
<li>Microsoft AKS</li>
<li>VMware Tanzu</li>
</ul>
<h2>検証環境およびバージョン情報</h2>
<p>本記事では Kubernetes のマネージドサービスである <a href="https://aws.amazon.com/jp/eks/" target="_blank" rel="noopener">Amazon EKS</a> 上で PGO v5 のデプロイ・動作確認を行います。</p>
<p>環境の構成およびバージョン情報は以下のとおりです。各ソフトウェアは 2022 年 3 月時点での最新バージョンを利用しています。</p>
<ul>
<li>PGO 5.0.5</li>
<li>Amazon EKS
<ul>
<li>Kubernetes バージョン: 1.21</li>
<li>ノード数: 3ノード</li>
<li>ノードタイプ: t3.medium</li>
</ul>
</li>
<li>オブジェクトストレージ: Amazon S3</li>
<li>ローカル作業環境: CentOS 7.9 (VirtualBox 上の VM)</li>
</ul>
<h2>検証内容</h2>
<p>本記事では、PGO v5 を用いて PostgreSQL クラスタを構築し、以下の機能について動作確認を行います。</p>
<ul>
<li>PGO のデプロイ</li>
<li>PostgreSQL クラスタの作成</li>
<li>psql による接続確認</li>
<li>PostgreSQL の設定</li>
<li>フェイルオーバー</li>
<li>スケーリング</li>
<li>ボリュームサイズの拡張</li>
<li>バックアップ</li>
<li>リストア・PITR</li>
<li>モニタリング</li>
</ul>
<h2>前提条件</h2>
<p>PGO をデプロイする前に、次の準備が完了していることが前提となります。</p>
<ul>
<li style="list-style-type: none;">
<ul>
<li>EKS クラスタの作成 (<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-cluster.html" target="_blank" rel="noopener">こちら</a>を参照)</li>
<li>Amazon S3 バケットの作成 (<a href="https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/creating-bucket.html" target="_blank" rel="noopener">こちら</a>を参照)<br />
※作成したバケットの名前は PostgresCluster (後述) の YAML ファイルに設定します。</li>
</ul>
</li>
</ul>
<h2>PGO のデプロイ</h2>
<p>PGO v5 以降、PGO のデプロイは Kustomize または Helm を使うことになりました。本記事では、Kustomize を用いて PGO をデプロイします。</p>
<p>各種サンプル設定ファイルを含む<a href="https://github.com/CrunchyData/postgres-operator-examples" target="_blank" rel="noopener">postgres-operator-examples</a>リポジトリを作業環境に複製します。</p>
<pre>$ git clone https://github.com/CrunchyData/postgres-operator-examples.git
$ cd postgres-operator-examples/</pre>
<p>PGO をデプロイします。</p>
<pre>$ kubectl apply -k kustomize/install</pre>
<p>上記コマンドを実行すると、postgres-operator という名前空間が作成され、PGO のデプロイに必要なすべてのオブジェクトがこの名前空間に作成されます。</p>
<pre>$ kubectl get pods -n postgres-operator
NAME                   READY   STATUS    RESTARTS   AGE
pgo-59c4f987b6-cd6pn   1/1     Running   0          29s</pre>
<h2>ストレージクラスの作成</h2>
<p>Amazon EKS ではデフォルトで gp2 という名前のストレージクラスが作成されていますが、本記事では以下の属性を持つ PGO 専用のストレージクラスを作成します。</p>
<ul>
<li><code><strong>allowVolumeExpansion</strong></code>: ボリュームの拡張を許可するように true を設定する。</li>
<li><code><strong>reclaimPolicy</strong></code>: PVC が削除された際に PV を残すように Retain を設定する。</li>
</ul>
<pre>$ cat &gt; ~/pgo-sc.yaml &lt;&lt;EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: pgo
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ext4
allowVolumeExpansion: true
reclaimPolicy: Retain
EOF

$ kubectl apply -f ~/pgo-sc.yaml
</pre>
<p>作成したストレージクラス pgo を確認します。</p>
<pre>$ kubectl get sc pgo
NAME   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
pgo    kubernetes.io/aws-ebs   <strong>Retain</strong>          Immediate           <strong>true</strong>                   6m36s
</pre>
<h2>PostgreSQL クラスタの作成</h2>
<p>PostgreSQL クラスタをデプロイします。</p>
<p>今回は以下のような構成の PostgreSQL クラスタを作成します。</p>
<ul>
<li>master 1台、replica 2台</li>
<li>同期レプリケーション</li>
<li>自動フェイルオーバー (デフォルト)</li>
<li>WAL アーカイブ (デフォルト)</li>
<li>永続ボリュームと Amazon S3 にバックアップと WAL アーカイブを保存</li>
</ul>
<p>取得したバックアップや WAL アーカイブは永続ボリュームのほか、S3 や GCS、Azure Blob Storage などのオブジェクトストレージにも保存できます。今回は、Amazon S3 を使います。GCS や Azure Blob Storage の設定については、<a href="https://access.crunchydata.com/documentation/postgres-operator/v5/tutorial/backups/" target="_blank" rel="noopener">こちら</a>を参照してください。</p>
<p><a href="https://github.com/CrunchyData/postgres-operator-examples" target="_blank" rel="noopener">postgres-operator-examples</a> リポジトリに各種構成のサンプル設定ファイルが用意されているので、それらのファイルを元に設定ファイルを作成します。今回は S3 を利用するために、kustomize/s3 配下のサンプルファイルをコピーし、必要に応じて編集します。</p>
<pre>$ cp -r  kustomize/s3 kustomize/my-postgres</pre>
<p>PGO v5 では PostgresCluster リソース (CRD) を使って、PostgreSQL クラスタのデプロイ・管理を行います。 PostgresCluster 設定のサンプルは postgres.yaml ファイルに記述されているので、必要に応じて編集します。</p>
<p>今回は以下のような YAML ファイルを利用して PostgresCluster をデプロイします。</p>
<pre>$ cat kustomize/my-postgres/postgres.yaml
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: my-postgres
spec:
  image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.2-0
  postgresVersion: 14
  instances:
    - name: pg-1
      replicas: 3
      dataVolumeClaimSpec:
        accessModes:
        - "ReadWriteOnce"
        resources:
          requests:
            storage: 10Gi
        storageClassName: pgo
  backups:
    pgbackrest:
      image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.36-1
      configuration:
      - secret:
          name: pgo-s3-creds
      global:
        repo2-path: /pgbackrest/postgres-operator/my-postgres/repo2
      repos:
      - name: repo1
        volume:
          volumeClaimSpec:
            accessModes:
            - "ReadWriteOnce"
            resources:
              requests:
                storage: 10Gi
            storageClassName: pgo
      - name: repo2
        s3:
          bucket: "my-postgres"
          endpoint: "s3.us-west-2.amazonaws.com"
          region: "us-west-2"
  patroni:
    dynamicConfiguration:
      synchronous_mode: true
  users:
    - name: postgres
    - name: testuser
      databases:
        - testdb
</pre>
<p>パラメータの意味は以下のとおりです。</p>
<ul>
<li><code><strong>spec.instances.replicas</strong></code>: レプリカの数を指定します。上記設定では、master 1台、replica 2台の PostgreSQL クラスタが作成されます。</li>
<li><code><strong>spec.backups.pgbackrest.repos.name</strong></code>: バックアップと WAL アーカイブの保存先を設定します。repoN 形式で複数の保存先を指定可能です。上記設定では、永続ボリュームを repo1、S3 を repo2 と設定しています。</li>
<li><code><strong>spec.backups.pgbackrest.repos.s3</strong></code>: Amazon S3 バケット情報を設定します。今回は前述の「前提条件」であらかじめ作成したバケットを利用します。</li>
<li><code><strong>spec.instances.dataVolumeClaimSpec</strong></code>: PostgreSQL データ保存用の PVC を設定します。</li>
<li><code><strong>spec.backups.pgbackrest.repos.volume.volumeClaimSpec</strong></code>: バックアップと WAL アーカイブ保存用の PVC を設定します。</li>
<li><code><strong>spec.patroni.dynamicConfiguration.synchronous_mode</strong></code>: 同期レプリケーションを利用するか否かを true/false で設定します。</li>
<li><code><strong>spec.users</strong></code>: デプロイ時に作成する PostgreSQL ユーザとデータベースを指定します。上記設定では、postgres と testuser ユーザ、testdb データベースが作成され、testuser に testdb へのアクセス権限が付与されます。</li>
</ul>
<p>次に、Amazon S3 にアクセスするためのクレデンシャルを登録します。<code><strong>repoN</strong></code> には、上記 <code>postgres.yaml</code> に設定した S3 のリポジトリ名を指定します。</p>
<pre>$ cp kustomize/my-postgres/s3.conf{.example,}
$ vi kustomize/my-postgres/s3.conf
[global]
<strong>repo2</strong>-s3-key=<strong>&lt;アクセスキー&gt;</strong>
<strong>repo2</strong>-s3-key-secret=<strong>&lt;シークレットアクセスキー&gt;</strong>
</pre>
<p>マニフェストの設定が完了したら、PostgreSQL クラスタをデプロイします。</p>
<pre>$ kubectl apply -k kustomize/my-postgres/</pre>
<p>PostgreSQL クラスタの状態を確認します。3つの Pod が作成されます。各 Pod が master か replica かはラベルで確認できます。</p>
<pre>$ kubectl get pods -n postgres-operator --selector=postgres-operator.crunchydata.com/instance-set \
  -L postgres-operator.crunchydata.com/role
NAME                      READY   STATUS    RESTARTS   AGE     ROLE
my-postgres-pg-1-45cl-0   3/3     Running   0          7m14s   <strong>master</strong>
my-postgres-pg-1-ctj8-0   3/3     Running   0          7m14s   <strong>replica</strong>
my-postgres-pg-1-rgc4-0   3/3     Running   0          7m14s   <strong>replica</strong>
</pre>
<h2>psql による接続確認</h2>
<p>Kubernetes クラスタ内のノードから、または他の Pod からは上記の PostgreSQL の Pod に接続できますが、作業環境から psql でアクセスしたい場合は <code>kubectl</code> の <code>port-forward</code> 機能を利用します。<br />
ここでは master Pod の 5432 ポートをローカルの 5432 へポートフォワードを行います。<br />
※ <code>PG_CLUSTER_MASTER_POD</code> には master の Pod 名が入ります。</p>
<pre>$ PG_CLUSTER_MASTER_POD=$(kubectl get pod -n postgres-operator -o name -l postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/role=master)
$ kubectl -n postgres-operator port-forward "${PG_CLUSTER_MASTER_POD}" 5432:5432 &amp;
</pre>
<p>psql で接続します。<code>testuser</code> ユーザの情報を格納する Secret からデータベースの接続情報を取得します。</p>
<pre>$ PG_CLUSTER_USER_SECRET_NAME=my-postgres-pguser-testuser
$ PGPASSWORD=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.password | base64decode}}') \
PGUSER=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.user | base64decode}}') \
PGDATABASE=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.dbname | base64decode}}') \
psql -h localhost
Handling connection for 5432
psql (14.2)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-ECDSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

testdb=&gt; \du+
                                            List of roles
  Role name   |                         Attributes                         | Member of | Description 
--------------+------------------------------------------------------------+-----------+-------------
 _crunchyrepl | Replication                                                | {}        | 
 postgres     | Superuser, Create role, Create DB, Replication, Bypass RLS | {}        | 
 testuser     |                                                            | {}        |
</pre>
<p>次に、<code>postgres</code> スーパーユーザで接続し、レプリケーションの状態を確認します。</p>
<pre>$ PG_CLUSTER_USER_SECRET_NAME=my-postgres-pguser-postgres
$ PGPASSWORD=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.password | base64decode}}') \
PGUSER=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.user | base64decode}}') \
psql -h localhost
Handling connection for 5432
psql (14.2)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-ECDSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# select application_name, state, sync_state from pg_stat_replication;
    application_name     |   state   | sync_state 
-------------------------+-----------+------------
 my-postgres-pg-1-rgc4-0 | streaming | sync
 my-postgres-pg-1-ctj8-0 | streaming | async
(2 rows)
</pre>
<h2>PostgreSQL の設定</h2>
<p>PostgreSQL のパラメータは <code>spec.patroni.dynamicConfiguration.postgresql.parameters</code> で設定します。<br />
例えば、<code>log_statement: all</code> の設定を追加して適用すると、自動的に PostgreSQL に反映されます。</p>
<pre>vi kustomize/my-postgres/postgres.yaml
(以下を追加)
spec:
  patroni:
    dynamicConfiguration:
      synchronous_mode: true
<strong>      postgresql:
        parameters:
          log_statement: all</strong>

$ kubectl apply -k kustomize/my-postgres/
</pre>
<p>設定値が変更されていることを確認します。</p>
<pre>$ PG_CLUSTER_MASTER_POD=$(kubectl get pod -n postgres-operator -o name -l postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/role=master)
$ kubectl exec ${PG_CLUSTER_MASTER_POD} -n postgres-operator -it -- psql
Handling connection for 5432
psql (14.2)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-ECDSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# show log_statement;
 log_statement 
---------------
 all
(1 row)
</pre>
<p>ただし、PostgreSQL の Pod の再起動が必要になるパラメータもあります。<br />
例えば、<code>max_connections</code> の設定値を変更した場合、Pod の再起動が必要になります。<br />
以下のコマンドを実行し、アノテーションを編集することで、PGO が自動的に変更を検出し、1つずつ Pod の再起動を行います。</p>
<pre>$ kubectl patch postgrescluster/my-postgres -n postgres-operator --type merge \
  --patch '{"spec":{"metadata":{"annotations":{"restarted":"'"$(date)"'"}}}}'
</pre>
<h2>フェイルオーバー</h2>
<p>PostgreSQL の master Pod に故障が発生した場合は、自動的にフェイルオーバーしていずれかの replica が master に昇格します。また、定義した「あるべき状態」を満たすために、新たな replica が起動します。この節では、PGO のフェイルオーバーの動作を検証してみます。</p>
<p>まず、master Pod を削除します。</p>
<pre>$ PG_CLUSTER_MASTER_POD=$(kubectl get pod -n postgres-operator -o name -l postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/role=master)
$ kubectl delete ${PG_CLUSTER_MASTER_POD} -n postgres-operator
pod "my-postgres-pg-1-45cl-0" deleted</pre>
<p>すると、replica Pod「my-postgres-pg-1-ctj8-0」が master に昇格し、旧 master Pod が replica として再起動されることを確認できます。</p>
<pre>$ kubectl get pods -n postgres-operator --selector=postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/instance-set \
  -L postgres-operator.crunchydata.com/role
NAME                      READY   STATUS    RESTARTS   AGE   ROLE
my-postgres-pg-1-45cl-0   3/3     Running   0          74s   <strong>replica</strong>
my-postgres-pg-1-ctj8-0   3/3     Running   0          52m   <strong>master</strong>
my-postgres-pg-1-rgc4-0   3/3     Running   0          52m   <strong>replica</strong>
</pre>
<h2>スケーリング</h2>
<p>スケーリングとは、replica を追加または削除することです。<br />
PostgreSQL クラスタに replica を追加することをクラスタのスケールアップ、クラスタから replica を削除することをクラスタのスケールダウンといいます。<br />
スケーリングすることにより、データベースの負荷分散や耐障害性の向上を実現できます。</p>
<p>YAML ファイルの replicas の数を変更し、適用するだけで、簡単にクラスタのスケールアップ/スケールダウンを行えます。<br />
以下のように replicas の数を 3 から 4 に変更して適用すると、新しい replica Pod が起動します。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(replicas を 3 から 4 に変更)
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: my-postgres
spec:
  image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.2-0
  postgresVersion: 14
  instances:
    - name: pg-1
      <strong>replicas: 4</strong>
(省略)

$ kubectl apply -k kustomize/my-postgres/
</pre>
<p>新しい replica が起動することを確認します。</p>
<pre>$ kubectl get pods -n postgres-operator --selector=postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/instance-set \
  -L postgres-operator.crunchydata.com/role
NAME                      READY   STATUS    RESTARTS   AGE     ROLE
<strong>my-postgres-pg-1-2fzw-0   3/3     Running   0          27s     replica</strong>
my-postgres-pg-1-45cl-0   3/3     Running   0          8m14s   replica
my-postgres-pg-1-ctj8-0   3/3     Running   0          59m     master
my-postgres-pg-1-rgc4-0   3/3     Running   0          59m     replica

$ PG_CLUSTER_MASTER_POD=$(kubectl get pod -n postgres-operator -o name -l postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/role=master)
$ kubectl exec ${PG_CLUSTER_MASTER_POD} -n postgres-operator -it -- psql
Handling connection for 5432
psql (14.2)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-ECDSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# select application_name, state, sync_state from pg_stat_replication;
    application_name     |   state   | sync_state 
-------------------------+-----------+------------
 my-postgres-pg-1-45cl-0 | streaming | async
 my-postgres-pg-1-rgc4-0 | streaming | sync
 my-postgres-pg-1-2fzw-0 | streaming | async
(3 rows)
</pre>
<p>元の設定に戻したい場合には、replicas の数を 4 から 3 に減らすと、いずれかの replica Pod が削除されます。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(replicas を 4 から 3 に変更)
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: my-postgres
spec:
  image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.2-0
  postgresVersion: 14
  instances:
    - name: pg-1
      <strong>replicas: 3</strong>
(省略)

$ kubectl apply -k kustomize/my-postgres/
</pre>
<p>replica Pod が削除されていることを確認します。</p>
<pre>$ kubectl get pods -n postgres-operator --selector=postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/instance-set \
  -L postgres-operator.crunchydata.com/role
NAME                      READY   STATUS    RESTARTS   AGE   ROLE
my-postgres-pg-1-45cl-0   3/3     Running   0          15m   replica
my-postgres-pg-1-ctj8-0   3/3     Running   0          67m   master
my-postgres-pg-1-rgc4-0   3/3     Running   0          67m   replica
</pre>
<h2>ボリュームサイズの拡張</h2>
<p>Kubernetes では、ボリュームの拡張が許可される場合のみ、既存の永続ボリューム (PV) のサイズを拡張できます。ボリュームの拡張を許可するかはストレージクラスの <code>allowVolumeExpansion</code> 属性で設定します。</p>
<p>ボリュームの拡張を行う前に、デプロイ済みの PostgreSQL クラスタが利用しているストレージクラスの <code>allowVolumeExpansion</code> の設定値が true であることを確認します。</p>
<pre>$ kubectl get sc pgo
NAME   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
pgo    kubernetes.io/aws-ebs   Retain          Immediate           <strong>true</strong>                   97m
</pre>
<p>PV と PVC のサイズを確認します。</p>
<pre>$ kubectl get pv,pvc -n postgres-operator
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                            STORAGECLASS   REASON   AGE
persistentvolume/pvc-04060f68-9590-4af1-a341-2dd8e1b42055   <strong>10Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-repo1              pgo                     91m
persistentvolume/pvc-1e13602d-1455-46b7-bfb0-7dee549ac70f   <strong>10Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-rgc4-pgdata   pgo                     91m
persistentvolume/pvc-4dde75fe-c392-4f75-b483-326dcd6e5d46   <strong>10Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-45cl-pgdata   pgo                     91m
persistentvolume/pvc-ff62508e-e743-482d-a67b-19726c075c2c   <strong>10Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-ctj8-pgdata   pgo                     91m

NAME                                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/my-postgres-pg-1-45cl-pgdata   Bound    pvc-4dde75fe-c392-4f75-b483-326dcd6e5d46   <strong>10Gi</strong>       RWO            pgo            91m
persistentvolumeclaim/my-postgres-pg-1-ctj8-pgdata   Bound    pvc-ff62508e-e743-482d-a67b-19726c075c2c   <strong>10Gi</strong>       RWO            pgo            91m
persistentvolumeclaim/my-postgres-pg-1-rgc4-pgdata   Bound    pvc-1e13602d-1455-46b7-bfb0-7dee549ac70f   <strong>10Gi</strong>       RWO            pgo            91m
persistentvolumeclaim/my-postgres-repo1              Bound    pvc-04060f68-9590-4af1-a341-2dd8e1b42055   <strong>10Gi</strong>       RWO            pgo            91m
</pre>
<p>PostgreSQL のデータ保存用の PVC とバックアップ保存用の PVC の要求サイズを 20GB に変更してみます。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(省略)
spec:
  image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.2-0
  postgresVersion: 14
  instances:
    - name: pg-1
      replicas: 3
      dataVolumeClaimSpec:
        accessModes:
        - "ReadWriteOnce"
        resources:
          requests:
            <strong>storage: 20Gi</strong>
        storageClassName: pgo
  backups:
    pgbackrest:
      - name: repo1
        volume:
          volumeClaimSpec:
            accessModes:
            - "ReadWriteOnce"
            resources:
              requests:
                <strong>storage: 20Gi</strong>
            storageClassName: pgo
(省略)

$ kubectl apply -k kustomize/my-postgres/
</pre>
<p>PVC と PV のサイズが拡張されていることを確認します。</p>
<pre>$ kubectl get pv,pvc -n postgres-operator
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                            STORAGECLASS   REASON   AGE
persistentvolume/pvc-04060f68-9590-4af1-a341-2dd8e1b42055   <strong>20Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-repo1              pgo                     103m
persistentvolume/pvc-1e13602d-1455-46b7-bfb0-7dee549ac70f   <strong>20Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-rgc4-pgdata   pgo                     103m
persistentvolume/pvc-4dde75fe-c392-4f75-b483-326dcd6e5d46   <strong>20Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-45cl-pgdata   pgo                     103m
persistentvolume/pvc-ff62508e-e743-482d-a67b-19726c075c2c   <strong>20Gi</strong>       RWO            Delete           Bound    postgres-operator/my-postgres-pg-1-ctj8-pgdata   pgo                     103m

NAME                                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/my-postgres-pg-1-45cl-pgdata   Bound    pvc-4dde75fe-c392-4f75-b483-326dcd6e5d46   <strong>20Gi</strong>       RWO            pgo            103m
persistentvolumeclaim/my-postgres-pg-1-ctj8-pgdata   Bound    pvc-ff62508e-e743-482d-a67b-19726c075c2c   <strong>20Gi</strong>       RWO            pgo            103m
persistentvolumeclaim/my-postgres-pg-1-rgc4-pgdata   Bound    pvc-1e13602d-1455-46b7-bfb0-7dee549ac70f   <strong>20Gi</strong>       RWO            pgo            103m
persistentvolumeclaim/my-postgres-repo1              Bound    pvc-04060f68-9590-4af1-a341-2dd8e1b42055   <strong>20Gi</strong>       RWO            pgo            103m
</pre>
<p><code>allowVolumeExpansion</code> 機能に対応していないストレージでは、既存の永続ボリュームのサイズを拡張できないため、ボリュームサイズが大きい、新しい PostgreSQL クラスタを作成し、既存のクラスタと同期させる必要があります。詳細については<a href="https://access.crunchydata.com/documentation/postgres-operator/v5/tutorial/resize-cluster/#resize-pvcs-with-storageclass-that-does-not-allow-expansion" target="_blank" rel="noopener">こちら</a>を参照してください。</p>
<h2>バックアップ</h2>
<p>PGO のバックアップ/リストアは内部的に pgBackRest のバックアップ/リストアユーティリティを利用しています。定期的にフルバックアップまたは差分バックアップを取得することができます。バックアップのスケジュールは cron 表記で指定します。</p>
<p>定期バックアップのスケジュールは <code>spec.backups.pgbackrest.repos.schedules</code> で設定します。<br />
例えば、以下のように設定すると、毎日午前1時にフルバックアップ、4時間ごとに差分バックアップを実行するようになります。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(省略)
spec:
  backups:
    pgbackrest:
      image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.36-1
      configuration:
      - secret:
          name: pgo-s3-creds
      global:
        repo2-path: /pgbackrest/postgres-operator/my-postgres/repo2
      repos:
      - name: repo1
        volume:
          volumeClaimSpec:
            accessModes:
            - "ReadWriteOnce"
            resources:
              requests:
                storage: 10Gi
      - name: repo2
<strong>        schedules:
          full: "0 1 * * *"
          incremental: "0 */4 * * *"</strong>
        s3:
          bucket: "crunchy-pg-backup"
          endpoint: "s3.us-west-2.amazonaws.com"
          region: "us-west-2"
(省略)
</pre>
<h2>リストア</h2>
<h3>PostgreSQL クラスタの複製</h3>
<p>PGO v5 では、既存の PostgreSQL クラスタを複製できます。<br />
既存のクラスタを複製するには、<code>spec.dataSource.postgresCluster</code> にコピー元のクラスタ名、バックアップの格納先のリポジトリ名を指定します。</p>
<pre>spec:
<strong>  dataSource:
    postgresCluster:
      clusterName: my-postgres
      repoName: repo2</strong>
</pre>
<p>デフォルトでは最新のデータにリストアしますが、<code>spec.dataSource.postgresCluster.options</code> を指定して、特定の時点までリストア可能です。</p>
<pre>spec:
  dataSource:
    postgresCluster:
      clusterName: my-postgres
      repoName: repo2
<strong>      options:
      - --type=time
      - --target="2022-03-16 14:00:00+09"
</strong></pre>
<h3>既存の PostgreSQL クラスタの PITR</h3>
<p>起動中の PostgreSQL クラスタを以前の時点にリストアするには <code>spec.backups.pgbackrest.restore</code> を設定します。既存のデータディレクトリでリストアを実行するので、クラスタが一旦停止され、作成しなおされます。</p>
<p>例えば、2022-03-16 14:00:00 時点までリストアする場合は、以下の手順を実行します。</p>
<p>まず、PostgresCluster リソースを設定する YAML ファイル postgres.yaml を編集し、適用します。<br />
※この時点ではリストアが実行されません。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(省略)
spec:
  backups:
    pgbackrest:
<strong>      restore:
        enabled: true
        repoName: repo2
        options:
        - --type=time
        - --target="2022-03-16 14:00:00+09"</strong>
(省略)

$ kubectl apply -k kustomize/my-postgres/
</pre>
<p>次に、PostgresCluster のアノテーションを設定します。<br />
PostgresCluster のアノテーションを設定すると、リストアが実行されます。</p>
<pre>$ kubectl annotate postgrescluster my-postgres  -n postgres-operator --overwrite \
  postgres-operator.crunchydata.com/pgbackrest-restore=id1
</pre>
<p>リストア完了後、リストアの設定を無効にしておきます。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(省略)
spec:
  backups:
    pgbackrest:
<strong>      restore:
        enabled: false</strong>
(省略)

$ kubectl apply -k kustomize/my-postgres/
</pre>
<h2>モニタリング</h2>
<p>PGO は Prometheus によるモニタリング機能を提供しています。Kubernetes では Prometheus を利用した監視がよく使われています。Prometheus がクラスタの各種メトリクスを収集し、Grafana と連携して、Grafana のダッシュボードで Kubernetes クラスタと PostgreSQL を監視することができます。</p>
<p>モニタリング機能を利用するために、まず、各  Pod に Exporter サイドカーを追加する必要があります。</p>
<pre>$ vi kustomize/my-postgres/postgres.yaml
(省略)
spec:
<strong>  monitoring:
    pgmonitor:
      exporter:
        image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-5.0.5-0</strong>
(省略)

$ kubectl apply -k kustomize/my-postgres

$ kubectl get pods -n postgres-operator --selector=postgres-operator.crunchydata.com/cluster=my-postgres,postgres-operator.crunchydata.com/instance-set \
  -L postgres-operator.crunchydata.com/role
NAME                      READY   STATUS    RESTARTS   AGE     ROLE
my-postgres-pg-1-45cl-0   <strong>4/4</strong>     Running   0          3m4s    master
my-postgres-pg-1-ctj8-0  <strong> 4/4</strong>     Running   0          3m35s   replica
my-postgres-pg-1-rgc4-0   <strong>4/4</strong>     Running   0          2m14s   replica
</pre>
<p>次に、監視アプリケーション Prometheus、Grafana、Alertmanager をデプロイします。</p>
<p>Amazon EKS のデフォルトのストレージクラス gp2 を利用しても良いですが、今回は前述の手順で作成したストレージクラスを利用します。Prometheus、Grafana、Alertmanager の PVC を定義する YAML ファイルを編集します。<br />
※ デフォルトのストレージクラスを利用する場合は編集不要です。</p>
<pre>$ vi kustomize/monitoring/pvcs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app.kubernetes.io/name: pgo-monitoring
    vendor: crunchydata
  name: alertmanagerdata
spec:
(省略)
  <strong>storageClassName: pgo</strong>
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app.kubernetes.io/name: pgo-monitoring
    vendor: crunchydata
  name: grafanadata
spec:
(省略)
  <strong>storageClassName: pgo</strong>
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app.kubernetes.io/name: pgo-monitoring
    vendor: crunchydata
  name: prometheusdata
spec:
(省略)
  <strong>storageClassName: pgo</strong>
</pre>
<p>Prometheus、Grafana、Alertmanager をデプロイします。</p>
<pre>$ kubectl apply -k kustomize/monitoring</pre>
<p>Prometheus、Grafana、Alertmanager の Pod が起動していることを確認できます。</p>
<pre>$ kubectl get pods -n postgres-operator --selector=app.kubernetes.io/name=postgres-operator-monitoring
NAME                                   READY   STATUS    RESTARTS   AGE
crunchy-alertmanager-f7b79cbd8-lfv7s   1/1     Running   0          4m47s
crunchy-grafana-548446d646-lqw4l       1/1     Running   0          4m45s
crunchy-prometheus-556f754797-98lcn    1/1     Running   0          4m44s
</pre>
<p>作業環境のブラウザから Grafana にアクセスするために、Grafana Pod の 3000 ポートをローカルの 3000 へポートフォワードを行います。</p>
<pre>$ GRAFANA_POD=$(kubectl get pod -n postgres-operator -o name -l app.kubernetes.io/name=postgres-operator-monitoring,name=crunchy-grafana)
$ kubectl -n postgres-operator port-forward ${GRAFANA_POD} 3000:3000 &amp;</pre>
<p>ブラウザで http://localhost:3000/ にアクセスすると、Grafana のログイン画面が表示されます。Grafana のログインユーザ名とパスワードは以下のコマンドで確認できます。</p>
<pre>$ kubectl get secret grafana-secret -n postgres-operator -ojsonpath='{.data.username}' | base64 --decode ; echo 
$ kubectl get secret grafana-secret -n postgres-operator -ojsonpath='{.data.password}' | base64 --decode ; echo
</pre>
<p>Grafana にログインし、ダッシュボードで Kubernetes クラスタや PostgreSQL の稼働状況を確認できます。</p>
<p><img fetchpriority="high" decoding="async" class="alignnone size-large wp-image-9430" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-1024x495.png" alt="" width="1024" height="495" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-1024x495.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-300x145.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-768x371.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-1536x742.png 1536w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-304x147.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana-282x136.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/03/crunchy-grafana.png 1919w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h2>おわりに</h2>
<p>今回は Crunchy Postgres Operator v5 について紹介しました。</p>
<p>インストールや管理方法が大幅に変更され、kubectl が使用できるようになり、以前のバージョンより構築・管理がさらに容易になりました。さらに詳しく知りたい方は、<a href="https://access.crunchydata.com/documentation/postgres-operator/v5/" target="_blank" rel="noopener">公式ドキュメント</a>をご覧ください。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Charmed Kubernetes の永続ストレージ</title>
		<link>https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-persistent-volume/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Mon, 14 Mar 2022 04:00:50 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Canonical]]></category>
		<category><![CDATA[Charmed Kubernetes]]></category>
		<category><![CDATA[Persistent Volume]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=9008</guid>

					<description><![CDATA[前回の記事では、Canonical Kubernetes ディストリビューション Charmed Kubernetes の特長、構築方法などを紹介しました。 Kubernetes を用いて簡単にコンテナとしてアプリケーシ ...]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-intro">前回</a>の記事では、Canonical Kubernetes ディストリビューション Charmed Kubernetes の特長、構築方法などを紹介しました。</p>
<p>Kubernetes を用いて簡単にコンテナとしてアプリケーションをデプロイ・削除をできるのがメリットですが、コンテナを削除するとコンテナ内のデータも削除されてしまいます。そのため、データベースのようなステートフルアプリケーションを利用する場合には、データの永続化が必要となります。</p>
<p><span id="more-9008"></span>今回は Charmed Kubernetes の永続ストレージ機能を紹介し、Charmed Kubernetes 上でのステートフルアプリケーションの構築について紹介します。</p>
<h2>Kubernetes の永続ストレージ</h2>
<p>Kubernetes の Podを削除すると Pod 内に保存されていたデータも一緒に削除されてしまいますので、データの永続化はできません。Kubernetes ノード上の領域を Pod にマウントすることで、Pod を削除した後もデータはノードに残るため、データの永続化は可能ですが、Pod が別ノードに再スケジュールされた場合にはデータの再利用ができないというデメリットがあります。</p>
<p>Kubernetes ノードとは別に外部ストレージを利用することで、Pod が削除されてもデータは外部ストレージに存在するため、データの永続化が可能です。また、外部ストレージはノードとは独立して存在しており、Pod が別のノードで再起動したとしてもデータが外部に存在するため、データの再利用が可能です。</p>
<p>Kubernetes でデータ永続化を実現するために、以下のリソースを利用します。</p>
<ul>
<li>PersistentVolume (PV)</li>
<li>PersistentVolumeClaim (PVC)</li>
<li>StorageClass</li>
</ul>
<p>事前に永続ボリューム (PersistentVolume) リソースを Kubernetes 上に作成しておき、Pod デプロイ時に PersistentVolumeClaim によって PersistentVolume が要求されると、Kubernetes は事前に作成しておいた PersistentVolume から要求に適したものを Pod に割り当てます。このような方法では、予め PersistentVolume を作成する手間がかかり、また、PersistentVolumeClaim の要求以上の容量の PersistentVolume が割り当てられてしまうという問題があります。</p>
<p>これに対して、PersistentVolume を動的に作成する仕組み Dynamic Provisioning を利用することができます。Dynamic Provisioning は StorageClass を利用し、PersistentVolumeClaim によって PersistentVolume が要求されたタイミングで PersistentVolume を動的に作成し、Pod に割り当てます。Dynamic Provisioning を利用することで、事前に PersistentVolume を作成する手間が省けます。また、PersistentVolumeClaim の要求よりも大きい容量の PersistentVolume が作成されることも回避できます。</p>
<p>本稿では Charmed Kubernetes 上で Dynamic Provisioning を利用したデータ永続化のソリューションを紹介します。</p>
<h2>Charmed Kubernetes の永続ストレージ</h2>
<p>Charmed Kubernetes で以下の方法を用いてデータの永続化を実現することができます。</p>
<h3>クラウドのストレージソリューション</h3>
<p>Charmed Kubernetes のクラウド基盤統合機能を利用すると、クラウドベンダーによって提供されているストレージソリューションをすぐに使用できます。</p>
<p>例えば、OpenStack 統合機能を有効にして Charmed Kubernetes をデプロイすると、cdk-cinder という名前の StorageClass が自動的に作成されます。</p>
<h3>Ceph</h3>
<p>Ceph Charm を用いてデプロイした Ceph クラスタを外部ストレージとして使用し、PersistentVolume を作成します。</p>
<h3>NFS</h3>
<p>NFS Charm を用いてデプロイした NFS サーバを外部ストレージとして使用し、PersistentVolume を作成します。</p>
<p>ベアメタルにデプロイされた Kubernetes では、クラウドの機能を利用できないため、Ceph や NFS を利用することになります。本稿では、Juju を用いて Charmed Kubernetes 上に Ceph を構築し、ステートフルアプリケーションのデータの永続化を実現する方法を紹介します。</p>
<h2>前提条件</h2>
<p>Charmed Kubernetes のデプロイが既に完了していることが前提となっています。今回は AWS 上にデプロイした Charmed Kubernetes を利用します。(デプロイ方法は<a href="https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-intro">こちら</a>を参照)</p>
<h2>Ceph ストレージの構築</h2>
<p>Ceph はオープンソースの分散ストレージソフトウェアです。</p>
<p>Kubernetes の永続ストレージに Ceph を利用すると、拡張可能な高可用ストレージを実現することができます。本節では、Juju を用いた Ceph ストレージの構築方法を説明します。</p>
<p>デプロイ済みの Charmed Kubernetes クラスタにアクセスし、ノード状態を確認します。まだデプロイしていない場合は、<a href="https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-intro">こちら</a>のデプロイ手順を参照してください。</p>
<pre>$ kubectl get node
NAME               STATUS   ROLES    AGE     VERSION
ip-172-31-54-236   Ready    &lt;none&gt;   9m48s   v1.23.4
ip-172-31-7-84     Ready    &lt;none&gt;   9m43s   v1.23.4
ip-172-31-90-192   Ready    &lt;none&gt;   9m43s   v1.23.4</pre>
<p>セキュリティの観点から、モデルを分けることをお勧めしますが、本稿は Charmed Kubernetes 上で Ceph による Dynamic Provisioning を検証することが目的なので、Kubernetes と Ceph を同一 モデルにデプロイします。</p>
<p>Charmed Kubernetes がデプロイされているモデルに切り替えます。</p>
<pre>$ juju switch k8s</pre>
<p>Ceph Monitor ノードをデプロイします。</p>
<p>Ceph Monitor はクラスタの管理、状態監視を行うコンポーネントです。高可用性を実現するために、3台以上の奇数台が必要です。ここでは、3台の Ceph Monitor ノードをデプロイします。</p>
<pre>$ juju deploy -n 3 ceph-mon</pre>
<p>Ceph OSD ノードをデプロイします。</p>
<p>Ceph OSD はデータの保存、データの冗長化などを行うコンポーネントです。<br />
Juju の <a href="https://charmhub.io/ceph-osd">ceph-osd</a> Charm では、<code>--storage</code> オプションに2種類のストレージを設定できます。</p>
<ul>
<li><code>osd-devices</code>: データを格納するストレージ</li>
<li><code>osd-journals</code>: ジャーナルを格納するストレージ</li>
</ul>
<p><code>--storage</code> オプションは <code>&lt;storage pool&gt;,&lt;size&gt;,&lt;number&gt;</code> 形式で指定します。</p>
<ul>
<li><code>storage pool</code>: ストレージプールを指定します。ストレージプールはクラウド基盤に依存します。指定しない場合は、クラウド基盤のデフォルトのストレージプールを使用します。AWS のデフォルトのストレージプールは ebs となります。</li>
<li><code>size</code>: 各ボリュームのサイズを指定します。</li>
<li><code>number</code>: ボリュームの数を指定します。</li>
</ul>
<p>ここでは、3台の Ceph OSD ノードをデプロイします。各 OSD ノードに2つのデータ用のボリューム（50GB）と1つのジャーナル用のボリューム（10GB）を作成します。</p>
<pre>$ juju deploy -n 3 ceph-osd --storage osd-devices=50G,2 --storage osd-journals=10G,1</pre>
<p>Ceph Monitor と Ceph OSD の関連付けを行います。</p>
<pre>$ juju add-relation ceph-osd ceph-mon</pre>
<p>RBD で作成した PersistentVolume のアクセスモードが ReadWriteOnce となりますので、アクセスモード ReadWriteMany の PersistentVolume を利用する場合には、CephFS をデプロイする必要があります。利用する場合には、以下のコマンドを実行し、CephFS のデプロイおよび関連付けの設定を行います。</p>
<pre>$ juju deploy -n 1 ceph-fs
$ juju add-relation ceph-fs ceph-mon</pre>
<p>Charmed Kubernetes で Ceph ストレージを利用するために、関連付けの設定を行います。</p>
<pre>$ juju add-relation ceph-mon:admin kubernetes-master
$ juju add-relation ceph-mon:client kubernetes-master</pre>
<p>Charmed Kubernetes と Ceph の関連付けの設定が完了したら、<code>kubectl get sc</code> を実行し、StorageClass が表示されていることを確認します。<br />
※cephfs ストレージクラスは、ceph-fs をデプロイした場合にのみ表示されます。</p>
<pre>$ kubectl get sc
NAME                PROVISIONER         RECLAIMPOLICY   VOLUMEBINDINGMODE  ALLOWVOLUMEEXPANSION  AGE
ceph-ext4           rbd.csi.ceph.com    Delete          Immediate          true                  2m39s
ceph-xfs (default)  rbd.csi.ceph.com    Delete          Immediate          true                  2m39s
cephfs              cephfs.csi.ceph.com Delete          Immediate          true                  2m39s</pre>
<p>Pod の状態を確認します。<br />
※cephfs の Pod は、ceph-fs をデプロイした場合にのみ表示されます。</p>
<pre>$ kubectl get pod
NAME                                            READY   STATUS    RESTARTS   AGE
csi-cephfsplugin-927cv                          3/3     Running   0          18s
csi-cephfsplugin-b6q66                          3/3     Running   0          22s
csi-cephfsplugin-provisioner-6f7ffd894d-b2sh4   6/6     Running   0          101s
csi-cephfsplugin-provisioner-6f7ffd894d-d5b9x   6/6     Running   0          101s
csi-cephfsplugin-provisioner-6f7ffd894d-kqvxn   6/6     Running   0          101s
csi-cephfsplugin-vqgtb                          3/3     Running   0          15s
csi-rbdplugin-fsh7g                             3/3     Running   0          15s
csi-rbdplugin-nt2lq                             3/3     Running   0          22s
csi-rbdplugin-provisioner-7dffff7f4d-8l8l5      7/7     Running   0          101s
csi-rbdplugin-provisioner-7dffff7f4d-wmvct      7/7     Running   0          101s
csi-rbdplugin-provisioner-7dffff7f4d-z7nm9      7/7     Running   0          101s
csi-rbdplugin-ts8rw                             3/3     Running   0          19s</pre>
<p>これで Ceph クラスタを Charmed Kubernetes の外部ストレージとして使用し Dynamic Provisioning を実現するための準備が完了です。</p>
<h3>スケールアウト</h3>
<p>Ceph のスケールアウトとは、新しいノードまたはデバイスを追加することによって利用可能な容量を拡張することです。本節では Ceph のスケールアウト手順について説明します。</p>
<p>Ceph ストレージの容量を拡張するには、Ceph OSD ノードを追加するか、既存の Ceph OSD ノードにストレージを追加します。</p>
<p>まず、既存のストレージの割り当てを確認します。</p>
<pre>$ juju storage
Unit        Storage id      Type   Pool  Size   Status    Message
ceph-osd/0  osd-devices/0   block  ebs   50GiB  attached  
ceph-osd/0  osd-devices/1   block  ebs   50GiB  attached  
ceph-osd/0  osd-journals/2  block  ebs   10GiB  attached  
ceph-osd/1  osd-devices/3   block  ebs   50GiB  attached  
ceph-osd/1  osd-devices/4   block  ebs   50GiB  attached  
ceph-osd/1  osd-journals/5  block  ebs   10GiB  attached  
ceph-osd/2  osd-devices/6   block  ebs   50GiB  attached  
ceph-osd/2  osd-devices/7   block  ebs   50GiB  attached  
ceph-osd/2  osd-journals/8  block  ebs   10GiB  attached</pre>
<p>新しい Ceph OSD ノードを追加します。</p>
<pre>$ juju add-unit ceph-osd -n 1</pre>
<p>新しいノード ceph-osd/3 が追加されていることを確認します。</p>
<pre>$ juju storage
Unit        Storage id       Type   Pool  Size   Status    Message
ceph-osd/0  osd-devices/0    block  ebs   50GiB  attached  
ceph-osd/0  osd-devices/1    block  ebs   50GiB  attached  
ceph-osd/0  osd-journals/2   block  ebs   10GiB  attached  
ceph-osd/1  osd-devices/3    block  ebs   50GiB  attached  
ceph-osd/1  osd-devices/4    block  ebs   50GiB  attached  
ceph-osd/1  osd-journals/5   block  ebs   10GiB  attached  
ceph-osd/2  osd-devices/6    block  ebs   50GiB  attached  
ceph-osd/2  osd-devices/7    block  ebs   50GiB  attached  
ceph-osd/2  osd-journals/8   block  ebs   10GiB  attached  
<strong>ceph-osd/3  osd-devices/10   block  ebs   50GiB  attached  
ceph-osd/3  osd-devices/9    block  ebs   50GiB  attached  
ceph-osd/3  osd-journals/11  block  ebs   10GiB  attached</strong>

$ juju status ceph-osd
Model  Controller      Cloud/Region   Version  SLA          Timestamp
k8s    k8s-controller  aws/us-east-1  2.9.22   unsupported  15:39:18+09:00

App       Version  Status  Scale  Charm     Store     Channel  Rev  OS      Message
ceph-osd  15.2.14  active      4  ceph-osd  charmhub  stable   513  ubuntu  Unit is ready (2 OSD)

Unit         Workload  Agent  Machine  Public address  Ports  Message
ceph-osd/0*  active    idle   13       3.83.100.242           Unit is ready (2 OSD)
ceph-osd/1   active    idle   14       3.238.52.73            Unit is ready (2 OSD)
ceph-osd/2   active    idle   15       3.235.171.220          Unit is ready (2 OSD)
<strong>ceph-osd/3   active    idle   17       54.82.234.9            Unit is ready (2 OSD)</strong>

Machine  State    DNS            Inst id              Series  AZ          Message
13       started  3.83.100.242   i-074dcc388f5b35c1b  focal   us-east-1d  running
14       started  3.238.52.73    i-0b2d721800fd923d6  focal   us-east-1c  running
15       started  3.235.171.220  i-0e9916138314d204b  focal   us-east-1f  running
<strong>17       started  54.82.234.9    i-0cf8cad9824868068  focal   us-east-1a  running</strong></pre>
<p>既存の Ceph OSD ノードにストレージを追加するために、<code>juju add-storage</code> コマンドを実行します。以下のコマンドを実行し、ceph-osd/0 ノードに 50GB の新しいボリュームを追加します。</p>
<pre>$ juju add-storage ceph-osd/0 osd-devices=50G,1</pre>
<p>ceph-osd/0 ノードに 50GB のボリュームが追加されていることを確認します。</p>
<pre>$ juju storage
Unit        Storage id       Type   Pool  Size   Status    Message
ceph-osd/0  osd-devices/0    block  ebs   50GiB  attached  
ceph-osd/0  osd-devices/1    block  ebs   50GiB  attached  
<strong>ceph-osd/0  osd-devices/12   block  ebs   50GiB  attached</strong>  
ceph-osd/0  osd-journals/2   block  ebs   10GiB  attached  
ceph-osd/1  osd-devices/3    block  ebs   50GiB  attached  
ceph-osd/1  osd-devices/4    block  ebs   50GiB  attached  
ceph-osd/1  osd-journals/5   block  ebs   10GiB  attached  
ceph-osd/2  osd-devices/6    block  ebs   50GiB  attached  
ceph-osd/2  osd-devices/7    block  ebs   50GiB  attached  
ceph-osd/2  osd-journals/8   block  ebs   10GiB  attached  
ceph-osd/3  osd-devices/10   block  ebs   50GiB  attached  
ceph-osd/3  osd-devices/9    block  ebs   50GiB  attached  
ceph-osd/3  osd-journals/11  block  ebs   10GiB  attached</pre>
<h2>アプリケーションをデプロイしてみる</h2>
<p>Charmed Kubernetes の永続ストレージの動的プロビジョニング機能を検証するために、ステートフルアプリケーションをデプロイしてみます。</p>
<p>本稿では、ステートフルアプリケーションとして PostgreSQL を扱います。</p>
<p>Kubernetes 上で PostgreSQL を動かすために、PostgreSQL Operator が必要になります。PostgreSQL Operator は PostgreSQL のデプロイや管理を自動化するためのソフトウェアです。</p>
<p>今回は検証目的で Charmed Kubernetes 環境向けに開発された <a href="https://charmhub.io/postgresql-k8s">PostgreSQL Charm</a>を利用して PostgreSQL を構築します。現時点では、PostgreSQL  Charm はスケーリングとフェイルオーバにのみ対応しており、バックアップやリストア・PITR などの管理は手動で行う必要があるため、本番環境での利用はお勧めしません。</p>
<p>本番環境で PostgreSQL をデプロイする場合は、以前の記事で紹介した <a href="https://www.sraoss.co.jp/tech-blog/pgsql/crunchy-postgresql-operator/">Crunchy PostgreSQL Operator</a> または <a href="https://www.sraoss.co.jp/tech-blog/pgsql/zalando-postgres-operator/">Zalando PostgreSQL Operator</a> を利用すると良いと思います。</p>
<p>Charmed Kubernetes  上に Juju チャームをデプロイするために、デプロイ済みの Charmed Kubernetes を Juju に登録する必要があります。</p>
<p><code>juju add-k8s</code> コマンドを実行し、Charmed Kubernetes 環境を登録します。ここでは、my-k8s という名前で 登録します。</p>
<pre>$ juju add-k8s my-k8s</pre>
<p>pg-controller という名前でコントローラーをデプロイします。</p>
<pre>$ juju bootstrap my-k8s pg-controller</pre>
<p>PostgreSQL をデプロイするためのモデルを作成します。モデル名と同じ名前の Namespace が Kubernetes に作成され、PostgreSQL がこの Namespace にデプロイされます。</p>
<p>ここで pg-model という名前のモデルを作成します。</p>
<pre>$ juju add-model pg-model</pre>
<p>次に、PostgreSQL をデプロイします。</p>
<p>PostgreSQL Charm の &#8211;storage オプションに2種類のストレージを設定できます。</p>
<ul>
<li><code>pgdata</code>: データベースのデータを格納するストレージ</li>
<li><code>logs</code>: PostgreSQL のログを格納するストレージ</li>
</ul>
<pre>$ juju deploy postgresql-k8s -n 3 --storage pgdata=20G --storage logs=1G</pre>
<p>上記コマンドを実行すると、primary 1台、replica 2台 の PostgreSQL クラスタが作成されます。</p>
<pre>$ kubectl get pod -n pg-model
NAME                             READY   STATUS    RESTARTS   AGE
modeloperator-7896f7f67d-pwch5   1/1     Running   0          4m17s
postgresql-k8s-0                 1/1     Running   0          2m14s
postgresql-k8s-1                 1/1     Running   0          2m14s
postgresql-k8s-2                 1/1     Running   0          2m14s
postgresql-k8s-operator-0        1/1     Running   0          3m8s</pre>
<p>PersistentVolumeClaim (PVC) と PersistentVolume (PV) を確認してみましょう。<br />
PostgreSQL Charm の PVC によって PV が自動的に作成されていることを確認します。</p>
<pre>$ kubectl get pvc -n pg-model
NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
logs-2c7ce802-postgresql-k8s-0     Bound    pvc-265cd94c-77ec-4862-b021-b9d199326ef6   1Gi        RWO            ceph-xfs       2m52s
logs-2c7ce802-postgresql-k8s-1     Bound    pvc-6f71aa9a-77fd-4de5-93a8-bcd4e88fe35d   1Gi        RWO            ceph-xfs       2m52s
logs-2c7ce802-postgresql-k8s-2     Bound    pvc-cbca4843-f12f-49e3-ae89-5436d9791819   1Gi        RWO            ceph-xfs       2m52s
pgdata-2c7ce802-postgresql-k8s-0   Bound    pvc-7b40a98c-6f00-4f64-8c0a-701ccc0515d3   20Gi       RWO            ceph-xfs       2m52s
pgdata-2c7ce802-postgresql-k8s-1   Bound    pvc-cd6415e2-2322-4b5f-89f2-640b8d65d515   20Gi       RWO            ceph-xfs       2m52s
pgdata-2c7ce802-postgresql-k8s-2   Bound    pvc-5eb9547b-e14a-42a3-9746-e012411121a7   20Gi       RWO            ceph-xfs       2m52s

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                           STORAGECLASS   REASON   AGE
pvc-2572bd8d-286f-4ffd-89b6-e22a95a11873   20Gi       RWO            Delete           Bound    controller-pg-controller/storage-controller-0   ceph-xfs                6m30s
pvc-265cd94c-77ec-4862-b021-b9d199326ef6   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-0         ceph-xfs                3m8s
pvc-5eb9547b-e14a-42a3-9746-e012411121a7   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-2       ceph-xfs                3m6s
pvc-6f71aa9a-77fd-4de5-93a8-bcd4e88fe35d   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-1         ceph-xfs                3m7s
pvc-7b40a98c-6f00-4f64-8c0a-701ccc0515d3   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-0       ceph-xfs                3m8s
pvc-cbca4843-f12f-49e3-ae89-5436d9791819   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-2         ceph-xfs                3m5s
pvc-cd6415e2-2322-4b5f-89f2-640b8d65d515   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-1       ceph-xfs                3m7s</pre>
<p>Replica の数を減らして、データが残るか検証します。</p>
<pre>$ juju remove-unit postgresql-k8s --num-units 1</pre>
<p>Pod が削除されても PVC と PV が削除されないことを確認します。</p>
<pre>$ kubectl get pod -n pg-model
NAME                             READY   STATUS    RESTARTS   AGE
modeloperator-7896f7f67d-pwch5   1/1     Running   0          6m22s
postgresql-k8s-0                 1/1     Running   0          4m19s
postgresql-k8s-1                 1/1     Running   0          4m19s
postgresql-k8s-operator-0        1/1     Running   0          5m13s

$ kubectl get pvc -n pg-model
NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
logs-2c7ce802-postgresql-k8s-0     Bound    pvc-265cd94c-77ec-4862-b021-b9d199326ef6   1Gi        RWO            ceph-xfs       4m37s
logs-2c7ce802-postgresql-k8s-1     Bound    pvc-6f71aa9a-77fd-4de5-93a8-bcd4e88fe35d   1Gi        RWO            ceph-xfs       4m37s
<strong>logs-2c7ce802-postgresql-k8s-2     Bound    pvc-cbca4843-f12f-49e3-ae89-5436d9791819   1Gi        RWO            ceph-xfs       4m37s</strong>
pgdata-2c7ce802-postgresql-k8s-0   Bound    pvc-7b40a98c-6f00-4f64-8c0a-701ccc0515d3   20Gi       RWO            ceph-xfs       4m37s
pgdata-2c7ce802-postgresql-k8s-1   Bound    pvc-cd6415e2-2322-4b5f-89f2-640b8d65d515   20Gi       RWO            ceph-xfs       4m37s
<strong>pgdata-2c7ce802-postgresql-k8s-2   Bound    pvc-5eb9547b-e14a-42a3-9746-e012411121a7   20Gi       RWO            ceph-xfs       4m37s</strong>

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                           STORAGECLASS   REASON   AGE
pvc-2572bd8d-286f-4ffd-89b6-e22a95a11873   20Gi       RWO            Delete           Bound    controller-pg-controller/storage-controller-0   ceph-xfs                8m30s
pvc-265cd94c-77ec-4862-b021-b9d199326ef6   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-0         ceph-xfs                5m8s
<strong>pvc-5eb9547b-e14a-42a3-9746-e012411121a7   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-2       ceph-xfs                5m6s</strong>
pvc-6f71aa9a-77fd-4de5-93a8-bcd4e88fe35d   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-1         ceph-xfs                5m7s
pvc-7b40a98c-6f00-4f64-8c0a-701ccc0515d3   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-0       ceph-xfs                5m8s
<strong>pvc-cbca4843-f12f-49e3-ae89-5436d9791819   1Gi        RWO            Delete           Bound    pg-model/logs-2c7ce802-postgresql-k8s-2         ceph-xfs                5m5s</strong>
pvc-cd6415e2-2322-4b5f-89f2-640b8d65d515   20Gi       RWO            Delete           Bound    pg-model/pgdata-2c7ce802-postgresql-k8s-1       ceph-xfs                5m7s</pre>
<h2>おわりに</h2>
<p>2回に渡って Canonical Kubernetes ディストリビューション Charmed Kubernetes を紹介しました。</p>
<p>エンタープライズ向けの機能を備えた Charmed Kubernetes は幅広いプラットフォームに対応しており、特にオンプレミスやプライベートクラウドにおいても容易に Kubernetes の環境を構築・管理できるという点は Charmed Kubernetes ならではの強みと言えます。オンプレミスやプライベートクラウドでエンタープライズ向けの Kubernetes を構築したい場合、Charmed Kubernetes は有力な選択肢だと言えるでしょう。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Canonical Kubernetes ディストリビューション Charmed Kubernetes の紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-intro/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Wed, 09 Mar 2022 05:00:03 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Canonical]]></category>
		<category><![CDATA[Charmed Kubernetes]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=8668</guid>

					<description><![CDATA[クラウドサービスは企業にとって今や欠かせないもののひとつとなっていますが、セキュリティやカスタマイズの自由度の観点から、プライベートクラウドやオンプレミスを選択する企業も増えています。しかし、オンプレミスやプライベートク ...]]></description>
										<content:encoded><![CDATA[<p>クラウドサービスは企業にとって今や欠かせないもののひとつとなっていますが、セキュリティやカスタマイズの自由度の観点から、プライベートクラウドやオンプレミスを選択する企業も増えています。しかし、オンプレミスやプライベートクラウドで Kubernetes 環境を構築し、エンタープライズレベルのセキュリティと信頼性で運用するのは簡単ではないです。</p>
<p><span id="more-8668"></span></p>
<p>Canonical 社が提供する <a href="https://ubuntu.com/kubernetes">Charmed Kubernetes</a> はパブリッククラウドからオンプレミスまで様々なプラットフォームに対応しており、サービスのデプロイツールである Juju を用いてオンプレミスやプライベートクラウドにおいても容易に Kubernetes の環境を構築・管理できます。</p>
<p>本記事では、 Charmed Kubernetes の特長、構築方法および主な機能について紹介します。</p>
<h2>Charmed Kubernetes とは</h2>
<p><a href="https://ubuntu.com/kubernetes">Charmed Kubernetes</a> は Linux ディストリビューション Ubuntu の開発元であるイギリスの Canonical 社が提供するエンタープライズ向けの Kubernetes ディストリビューションです。</p>
<p>パブリッククラウドからオンプレミスのプライベートクラウドや仮想化基盤、ベアメタルまで、幅広いプラットフォームに対応しており、高可用性、スケーリング、ダウンタイムなしのアップグレード、暗号化通信、永続ストレージなど、エンタープライズレベルのセキュリティと管理機能を備えています。</p>
<h2>Charmed Kubernetes の特長</h2>
<p>Charmed Kubernetes には次のような特長があります。</p>
<h3>クラウド基盤との統合</h3>
<p>Charmed Kubernetes は幅広いクラウド基盤と統合することができます。統合することによって、クラウドサービスのネイティブ機能を直接使用することもできます。例えば、AWSと統合することで、AWS が提供しているストレージサービス（EBS）やロードバランサーサービス（ELB）をデフォルトで利用可能です。</p>
<h3>アップストリーム Kubernetes の最新バージョン対応</h3>
<p>Charmed Kubernetes はアップストリーム Kubernetes と並行してリリースされているため、アップストリーム Kubernetes の最新バージョンへアップグレードすることができ、いち早く最新機能を活用することが可能です。</p>
<h3>幅広いプラットフォームに対応</h3>
<p>Charmed Kubernetes は幅広いプラットフォームに対応しています。現時点では以下のプラットフォームに対応しています。</p>
<ul>
<li>パブリッククラウド
<ul>
<li>Amazon AWS</li>
<li>Google GCE</li>
<li>Microsoft Azure</li>
<li>Oracle</li>
<li>Rackspace</li>
<li>Equinix Metal</li>
</ul>
</li>
<li>プライベートクラウド
<ul>
<li>OpenStack</li>
<li>VMware vSphere</li>
<li>MAAS</li>
</ul>
</li>
<li>ローカル
<ul>
<li>LXD</li>
</ul>
</li>
</ul>
<h3>可用性とセキュリティに優れたエンタープライズ向けの Kubernetes</h3>
<p>パブリッククラウドの場合は、クラウドベンダーが提供する機能によって、一部のデータセンターに障害が起きてもサービスが継続して利用できる構成となっています。一方、オンプレミスのプライベートクラウドの場合は、障害対策のためにサーバの冗長化やバックアップなどの措置が必要になります。</p>
<p>Charmed Kubernetes は高可用性機能を提供しており、一部のサーバに障害が起きても、Kubernetes クラスタが動作し続けます。また、Charmed Kubernetes のすべてのコンポーネントが TLS による暗号化通信を行うため、セキュアで堅牢な Kubernetes を実現できます。</p>
<h2>Juju とは</h2>
<p>Juju は Canonical 社が開発しているサービスをデプロイするための自動化ツールです。</p>
<p>Juju を用いて対応しているプラットフォーム上に複数の Ubuntu サーバの作成から、Kubernetes クラスタの構築まで、いくつかのコマンドを実行するだけで、簡単に行えます。</p>
<p>本記事では、Juju を用いて Charmed Kubernetes クラスタを構築し、以下の機能について動作確認を行います。</p>
<ul>
<li>スケーリング</li>
<li>アップグレード</li>
<li>モニタリング</li>
<li>永続ストレージ(<a href="https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-persistent-volume">こちら</a>を参照)</li>
</ul>
<h3>検証環境およびバージョン情報</h3>
<p>Charmed Kubernetes は様々なプラットフォーム上に構築できますが、本記事では気軽に利用できるパブリッククラウド AWS を使って Charmed Kubernetes を構築します。各ソフトウェアは投稿時点での最新バージョンを利用しています。</p>
<p>環境およびバージョン情報は以下の通りです。</p>
<ul>
<li>Kubernetes 1.23</li>
<li>Juju 2.9.22</li>
<li>ローカルの作業環境: Ubuntu 20.04.3 LTS (Focal Fossa)</li>
</ul>
<p>Juju がクラウドにアクセスするために、認証情報の登録が必要になります。<br />
AWS の場合は、アクセスキーとシークレットキーが必要になりますので、事前に確認しておいてください。</p>
<h2>Charmed Kubernetesのデプロイ</h2>
<h3>Juju のインストール</h3>
<p>Juju をインストールします。</p>
<pre>$ sudo snap install juju --classic</pre>
<h3>kubectl のインストール</h3>
<p><code>kubectl</code> をインストールします。</p>
<pre>$ sudo snap install kubectl --classic</pre>
<h3>クレデンシャルの追加</h3>
<p>Juju に AWS にアクセスするためのクレデンシャルを登録します。</p>
<pre>$ juju add-credential aws
Select region [any region, credential is not region specific]: &lt;任意のリージョンを指定&gt;
Using auth-type "access-key".
Enter access-key: &lt;アクセスキー&gt;
Enter secret-key: &lt;シークレットアクセスキー&gt;
Credential "aws" added locally for cloud "aws".</pre>
<p>登録後、以下のコマンドを実行し、AWS が登録されていることを確認します。</p>
<pre>$ juju clouds
...
Clouds available on the client:
Cloud      Regions  Default    Type  Credentials  Source    Description
<strong>aws        22       us-east-1  ec2   1            public    Amazon Web Services</strong>
localhost  1        localhost  lxd   0            built-in  LXD Container Hypervisor</pre>
<h3>Juju コントローラーのデプロイ</h3>
<p>Juju コントローラーをデプロイします。</p>
<p>Juju コントローラーは、Juju を使ってデプロイされたサービスを管理するために使用されます。以下のコマンドを実行すると、us-east-1 リージョンの EC2 インスタンスに Juju コントローラーがデプロイされます。リージョンを指定したい場合には、<code>juju bootstrap aws/&lt;リージョン&gt; &lt;コントローラー名&gt;</code>を実行してください。</p>
<pre>$ juju bootstrap aws k8s-controller</pre>
<p>デフォルトでは、 「mem=4G cores=2 」の <span id="detailsInstanceType" class="">t2.medium</span> タイプの EC2 インスタンスが Juju コントローラーのマシンとして作成されます。CPU やメモリを変更したい場合は、デプロイ時に <code>--bootstrap-constraints</code> を指定することでインスタンスタイプを変更できます。</p>
<pre>$ juju bootstrap --bootstrap-constraints "mem=8G cores=4" aws k8s-controller</pre>
<h3>モデルの作成</h3>
<p>Juju モデルはアプリケーションやマシンがデプロイされるワークスペースです。コントローラーは複数のモデルを持つことができますが、モデルは単一のコントローラーにしか関連付けられません。各モデルは複数のマシン、サービスを持つことができます。</p>
<p>サービスをデプロイする際に、デフォルトでは default というモデルにデプロイされますが、サービスごとにモデルを作成することを推奨されているため、ここでは Kubernetes 専用のモデルを作成します。</p>
<pre>$ juju add-model k8s
</pre>
<p>モデルが作成されていることを確認します。</p>
<pre>$ juju status
Model  Controller      Cloud/Region   Version  SLA          Timestamp
k8s    k8s-controller  aws/us-east-1  2.9.22   unsupported  12:02:03+09:00

$ juju models
Controller: k8s-controller

Model       Cloud/Region   Type  Status     Machines  Cores  Access  Last connection
controller  aws/us-east-1  ec2   available         1      2  admin   just now
default     aws/us-east-1  ec2   available         0      -  admin   53 seconds ago
k8s*        aws/us-east-1  ec2   available         0      -  admin   14 seconds ago</pre>
<h3>Kubernetes のデプロイ</h3>
<p>準備ができましたので、早速 Kubernetes をデプロイしましょう。</p>
<p>Juju を利用してアプリケーションをデプロイするには、Charm または Bundle を使います。</p>
<p>Charm を利用することで任意のマシンにアプリケーションをデプロイできます。複数アプリケーションから構成されるサービスでは、アプリケーションデプロイ後、アプリケーション同士の関連付けを設定する必要があります。Bundle は YAML 形式で記述したスクリプトファイルで、マシンの作成から、アプリケーションのデプロイ、そして関連付けまでの一連の処理を自動的にセットアップしてくれるツールです。</p>
<p>今回は Charm から Kubernetes をデプロイします。また、AWS のストレージサービスなどを利用するために、<code>--overlay</code> を利用してクラウド統合機能を有効にします。<code>--overlay</code> については後述します。デフォルトでは最新版がインストールされます。バージョンを指定してインストールを行う場合は<span class="aCOpRe ljeAnf">後述する</span> Bundle を使用したインストールを参照してください。</p>
<pre>$ wget https://raw.githubusercontent.com/charmed-kubernetes/bundle/master/overlays/aws-overlay.yaml
$ juju deploy charmed-kubernetes --overlay aws-overlay.yaml --trust</pre>
<p>すべてのアプリケーションのデプロイが完了するまで、15分~20分程度かかります。すべてのアプリケーション（App） の「Status」が「active」になったらデプロイ完了です。</p>
<p><code>juju status</code> コマンドで状態を確認してみましょう。</p>
<p>App には Kubernetes の各コンポーネント、Machine には各インスタンスが表示されます。デフォルトでは 11台のマシン（インスタンス）が立ち上がり、マスタノード2台、ワーカーノード3台の Kubernetes クラスタが構成されます。</p>
<pre>$ juju status
Model  Controller      Cloud/Region   Version  SLA          Timestamp
k8s    k8s-controller  aws/us-east-1  2.9.22   unsupported  12:27:04+09:00

App                    Version   Status  Scale  Charm                  Store       Channel   Rev  OS      Message
aws-integrator         1.15.58   active      1  aws-integrator         charmstore  stable    174  ubuntu  Ready
containerd             go1.13.8  active      5  containerd             charmstore  stable    200  ubuntu  Container runtime available
easyrsa                3.0.1     active      1  easyrsa                charmstore  stable    441  ubuntu  Certificate Authority connected.
etcd                   3.4.5     active      3  etcd                   charmstore  stable    655  ubuntu  Healthy with 3 known peers
flannel                0.11.0    active      5  flannel                charmstore  stable    619  ubuntu  Flannel subnet 10.1.6.1/24
kubeapi-load-balancer  1.18.0    active      1  kubeapi-load-balancer  charmstore  stable    866  ubuntu  Loadbalancer ready.
kubernetes-master      1.23.4    active      2  kubernetes-master      charmstore  stable   1106  ubuntu  Kubernetes master running.
kubernetes-worker      1.23.4    active      3  kubernetes-worker      charmstore  stable    838  ubuntu  Kubernetes worker running.

Unit                      Workload  Agent  Machine  Public address  Ports             Message
aws-integrator/0*         active    idle   0        54.196.183.155                    Ready
easyrsa/0*                active    idle   1        34.232.80.105                     Certificate Authority connected.
etcd/0                    active    idle   2        54.204.103.118  2379/tcp          Healthy with 3 known peers
etcd/1                    active    idle   3        3.236.214.69    2379/tcp          Healthy with 3 known peers
etcd/2*                   active    idle   4        44.198.164.226  2379/tcp          Healthy with 3 known peers
kubeapi-load-balancer/0*  active    idle   5        107.22.102.7    443/tcp,6443/tcp  Loadbalancer ready.
kubernetes-master/0*      active    idle   6        44.200.39.125   6443/tcp          Kubernetes master running.
  containerd/3            active    idle            44.200.39.125                     Container runtime available
  flannel/3               active    idle            44.200.39.125                     Flannel subnet 10.1.2.1/24
kubernetes-master/1       active    idle   7        3.83.124.151    6443/tcp          Kubernetes master running.
  containerd/0*           active    idle            3.83.124.151                      Container runtime available
  flannel/0               active    idle            3.83.124.151                      Flannel subnet 10.1.6.1/24
kubernetes-worker/0*      active    idle   8        54.160.123.197  80/tcp,443/tcp    Kubernetes worker running.
  containerd/1            active    idle            54.160.123.197                    Container runtime available
  flannel/1*              active    idle            54.160.123.197                    Flannel subnet 10.1.42.1/24
kubernetes-worker/1       active    idle   9        54.209.207.221  80/tcp,443/tcp    Kubernetes worker running.
  containerd/2            active    idle            54.209.207.221                    Container runtime available
  flannel/2               active    idle            54.209.207.221                    Flannel subnet 10.1.13.1/24
kubernetes-worker/2       active    idle   10       3.81.86.195     80/tcp,443/tcp    Kubernetes worker running.
  containerd/4            active    idle            3.81.86.195                       Container runtime available
  flannel/4               active    idle            3.81.86.195                       Flannel subnet 10.1.35.1/24

Machine  State    DNS             Inst id              Series  AZ          Message
0        started  54.196.183.155  i-02e9a6edcd5ac1cd5  focal   us-east-1a  running
1        started  34.232.80.105   i-05671fd8500a33119  focal   us-east-1f  running
2        started  54.204.103.118  i-0f28aea6be2d08e9d  focal   us-east-1d  running
3        started  3.236.214.69    i-0159b2e42b4b9c24e  focal   us-east-1f  running
4        started  44.198.164.226  i-0fd02e8e11ec1bfef  focal   us-east-1c  running
5        started  107.22.102.7    i-0bbd5a7a0ef45e4ef  focal   us-east-1b  running
6        started  44.200.39.125   i-05096429e51aeaa39  focal   us-east-1c  running
7        started  3.83.124.151    i-07c224c10603b0218  focal   us-east-1d  running
8        started  54.160.123.197  i-03a01a0e7b2bfe073  focal   us-east-1e  running
9        started  54.209.207.221  i-003d3e37b1a655e2e  focal   us-east-1a  running
10       started  3.81.86.195     i-001459c2be09d5db8  focal   us-east-1b  running</pre>
<h3>Charmed Kubernetes 設定のカスタマイズ</h3>
<p>Charmed Kubernetes の設定をカスタマイズする方法は2つあります。</p>
<ul>
<li>Bundle ファイルの使用</li>
<li>Overlay の使用</li>
</ul>
<h4>Bundle ファイルの使用</h4>
<p>Bundle ファイルは各種設定、デプロイの手順などを記載した YAML ファイルです。Bundle ファイルを必要に応じて編集することで、設定のカスタマイズが可能です。</p>
<p>特定の Kubernetes バージョンの Bundle ファイルは、<a href="https://ubuntu.com/kubernetes/docs/install-manual#table">こらち</a>からダウンロードできます。</p>
<p>一例として、v1.21 の Bundle ファイルをダウンロードし、ワーカーノードの数を変更してみます。</p>
<pre>$ wget https://api.jujucharms.com/charmstore/v5/charmed-kubernetes-733/archive/bundle.yaml
$ vi bundle.yaml
(ワーカーノードの数を3-&gt;4に変更)
...
kubernetes-worker:
annotations:
gui-x: '90'
gui-y: '850'
charm: cs:~containers/kubernetes-worker-838
constraints: cores=4 mem=4G root-disk=16G
expose: true
num_units: 4
...</pre>
<p>Bundle ファイルを用いてデプロイします。</p>
<pre>juju deploy ./bundle.yaml</pre>
<p><strong>Overlayの使用</strong></p>
<p><code>--overlay</code> オプションを利用することで、デフォルトの設定にマージ、またはデフォルトの設定を上書きすることができます。</p>
<p>例えば、Google Cloud 統合機能を利用する場合は、以下の設定を <code>--overla</code>y オプションに指定します。</p>
<pre>description: Charmed Kubernetes overlay to add native GCP support.
applications:
  gcp-integrator:
    annotations:
      gui-x: "600"
      gui-y: "300"
    charm: cs:~containers/gcp-integrator
    num_units: 1
    trust: true
relations:
  - ['gcp-integrator', 'kubernetes-master']
  - ['gcp-integrator', 'kubernetes-worker']</pre>
<p>各クラウドサービスむけの機能統合のYAMLファイルは<a href="https://ubuntu.com/kubernetes/docs/install-manual#cloud-integration">こちら</a>からダウンロードできます。</p>
<p>Google Cloud を利用する場合は、以下の手順を実行します。</p>
<pre>$ wget https://raw.githubusercontent.com/charmed-kubernetes/bundle/master/overlays/gcp-overlay.yaml
$ juju deploy charmed-kubernetes --overlay gcp-overlay.yaml --trust</pre>
<p>また、一部の設定を変更したい場合も、<code>--overlay</code> オプションが利用可能です。</p>
<p>例えば、ワーカーノードのデフォルトの制約は「constraints: cores=4 mem=4G root-disk=16G」となりますが、以下の設定を <code>--overlay</code> に設定することで、デフォルトの設定を上書きすることができます。</p>
<pre>$ cat myoverlay.yaml
applications:
  kubernetes-worker:
    constraints: cores=4 mem=8G root-disk=100G
    num_units: 3

$ juju deploy charmed-kubernetes --overlay myoverlay.yaml</pre>
<h3>Kubernetes クラスタへ接続</h3>
<p>Charmed Kubernetes のデプロイが完了したら、Kubernetes に接続してクラスタの状態を確認します。</p>
<p>まず、マスタノードから接続設定ファイルを取得します。</p>
<pre>$ mkdir -p .kube
$ juju scp kubernetes-master/0:config ~/.kube/config</pre>
<p>次に、馴染みのある <code>kubectl get</code> コマンドを実行し、ワーカーノードや Pod の状態を確認してみます。</p>
<pre>$ kubectl get nodes
NAME                            STATUS   ROLES    AGE   VERSION
ip-172-31-26-174.ec2.internal   Ready    &lt;none&gt;   21m   v1.23.4
ip-172-31-42-12.ec2.internal    Ready    &lt;none&gt;   19m   v1.23.4
ip-172-31-49-88.ec2.internal    Ready    &lt;none&gt;   22m   v1.23.4

$ kubectl get pods --all-namespaces
NAME                            STATUS   ROLES    AGE   VERSION
ip-172-31-26-174.ec2.internal   Ready    &lt;none&gt;   21m   v1.23.4
ip-172-31-42-12.ec2.internal    Ready    &lt;none&gt;   19m   v1.23.4
ip-172-31-49-88.ec2.internal    Ready    &lt;none&gt;   22m   v1.23.4

$ kubectl get pods --all-namespaces
NAMESPACE                         NAME                                                      READY   STATUS    RESTARTS   AGE
ingress-nginx-kubernetes-worker   default-http-backend-kubernetes-worker-6cd58d8886-nthsf   1/1     Running   0          21m
ingress-nginx-kubernetes-worker   nginx-ingress-controller-kubernetes-worker-mb75q          1/1     Running   0          21m
ingress-nginx-kubernetes-worker   nginx-ingress-controller-kubernetes-worker-vjp95          1/1     Running   0          19m
ingress-nginx-kubernetes-worker   nginx-ingress-controller-kubernetes-worker-wgbfj          1/1     Running   0          18m
kube-system                       coredns-5564855696-b2fcm                                  1/1     Running   0          25m
kube-system                       kube-state-metrics-5ccbcf64d5-5g49x                       1/1     Running   0          25m
kube-system                       metrics-server-v0.5.1-79b4746b65-bzhm5                    2/2     Running   0          25m
kubernetes-dashboard              dashboard-metrics-scraper-5cd54464bf-kc54z                1/1     Running   0          25m
kubernetes-dashboard              kubernetes-dashboard-55796c99c-r7v76                      1/1     Running   0          25m</pre>
<p>AWS 統合機能によって、デフォルトの StorageClass が自動的に作成されていることを確認します。</p>
<pre>$ kubectl get sc
NAME      PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
cdk-ebs   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  26m</pre>
<p>これで Kubernetes クラスタのデプロイは完了です。</p>
<h2>スケーリング</h2>
<p>Kubernetes クラスタのスケーリングとは、ワーカーノードを追加または削除することです。</p>
<p>Kubernetes クラスタにワーカーノードを追加することをクラスタのスケールアップ、クラスタからノードを削除することをクラスタのスケールダウンと言います。</p>
<p>Charmed Kubernetes では <code>juju add-unit/remove-unit</code> を実行することで、簡単にクラスタのスケールアップ/スケールダウンを行えます。</p>
<h3><strong>スケールアップ</strong></h3>
<p>新しいノードをクラスタに追加します。</p>
<pre>$ juju add-unit kubernetes-worker -n 1</pre>
<p>新しいワーカーノードが追加されていることを確認します。</p>
<pre>$ juju status
...
kubernetes-worker/0*      active    idle   8        54.160.123.197  80/tcp,443/tcp    Kubernetes worker running.
  containerd/1            active    idle            54.160.123.197                    Container runtime available
  flannel/1*              active    idle            54.160.123.197                    Flannel subnet 10.1.42.1/24
kubernetes-worker/1       active    idle   9        54.209.207.221  80/tcp,443/tcp    Kubernetes worker running.
  containerd/2            active    idle            54.209.207.221                    Container runtime available
  flannel/2               active    idle            54.209.207.221                    Flannel subnet 10.1.13.1/24
kubernetes-worker/2       active    idle   10       3.81.86.195     80/tcp,443/tcp    Kubernetes worker running.
  containerd/4            active    idle            3.81.86.195                       Container runtime available
  flannel/4               active    idle            3.81.86.195                       Flannel subnet 10.1.35.1/24
kubernetes-worker/3       active    idle   11       174.129.117.55  80/tcp,443/tcp    Kubernetes worker running.
  containerd/5            active    idle            174.129.117.55                    Container runtime available
  flannel/5               active    idle            174.129.117.55                    Flannel subnet 10.1.7.1/24


$ kubectl get node -o wide
NAME                            STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ip-172-31-26-174.ec2.internal   Ready       44m   v1.23.4   172.31.26.174   54.209.207.221   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-42-12.ec2.internal    Ready       42m   v1.23.4   172.31.42.12    3.81.86.195      Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-49-88.ec2.internal    Ready       45m   v1.23.4   172.31.49.88    54.160.123.197   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-83-85.ec2.internal    Ready       13m   v1.23.4   172.31.83.85    174.129.117.55   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5</pre>
<h3><strong>スケールダウン</strong></h3>
<p>スケールダウンするときには、ノードを安全に停止・削除するために、その Node 上で実行中の Podを退去させてから、スケールダウンを行う必要があります。</p>
<p>検証用の Nginx の Pod をデプロイします。</p>
<pre>$ kubectl create deployment --image=nginx nginx</pre>
<p>Nginx の Pod がデプロイされているワーカーノードを確認します。「ip-172-31-83-85.ec2.internal」というノード（kubernetes-worker/3）にデプロイされています。今回は、kubernetes-worker/3 を削除してみます。</p>
<pre>$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP         NODE                           NOMINATED NODE   READINESS GATES
nginx-85b98978db-hsbvd   1/1     Running   0          2m41s   10.1.7.2   ip-172-31-83-85.ec2.internal</pre>
<p>ノードを安全に停止・削除するために、以下のコマンドを実行し、kubernetes-worker/3 上で動作中の Nginx の Pod を移動させ、新たに Pod がスケジュールされないようにします。</p>
<pre>$ juju run-action kubernetes-worker/3 pause --wait
unit-kubernetes-worker-3:
  UnitId: kubernetes-worker/3
  id: "2"
  results:
    Stderr: |
      WARNING: ignoring DaemonSet-managed Pods: ingress-nginx-kubernetes-worker/nginx-ingress-controller-kubernetes-worker-rwt52
  status: completed
  timing:
    completed: 2022-02-16 04:14:20 +0000 UTC
    enqueued: 2022-02-16 04:14:16 +0000 UTC
    started: 2022-02-16 04:14:17 +0000 UTC</pre>
<p>上記コマンドを実行すると、ノードが SchedulingDisabled になり、Pod が別のノード上で起動していることを確認できます。</p>
<pre>$ kubectl get node -o wide
NAME                            STATUS                     ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ip-172-31-26-174.ec2.internal   Ready                         55m   v1.23.4   172.31.26.174   54.209.207.221   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-42-12.ec2.internal    Ready                         53m   v1.23.4   172.31.42.12    3.81.86.195      Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-49-88.ec2.internal    Ready                         56m   v1.23.4   172.31.49.88    54.160.123.197   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-83-85.ec2.internal    Ready,SchedulingDisabled      24m   v1.23.4   172.31.83.85    174.129.117.55   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5

$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP          NODE                           NOMINATED NODE   READINESS GATES
nginx-85b98978db-x9dzg   1/1     Running   0          2m5s   10.1.35.2   ip-172-31-42-12.ec2.internal</pre>
<p>これで、kubernetes-worker/3 ノードを安全に削除することができます。</p>
<pre>$ juju remove-unit kubernetes-worker/3</pre>
<p>しばらく経つと、kubernetes-worker/3 ノードが削除されていることを確認できます。</p>
<pre>$ juju status
...
kubernetes-worker/0*      active    idle   8        54.160.123.197  80/tcp,443/tcp    Kubernetes worker running.
  containerd/1            active    idle            54.160.123.197                    Container runtime available
  flannel/1*              active    idle            54.160.123.197                    Flannel subnet 10.1.42.1/24
kubernetes-worker/1       active    idle   9        54.209.207.221  80/tcp,443/tcp    Kubernetes worker running.
  containerd/2            active    idle            54.209.207.221                    Container runtime available
  flannel/2               active    idle            54.209.207.221                    Flannel subnet 10.1.13.1/24
kubernetes-worker/2       active    idle   10       3.81.86.195     80/tcp,443/tcp    Kubernetes worker running.
  containerd/4            active    idle            3.81.86.195                       Container runtime available
  flannel/4               active    idle            3.81.86.195                       Flannel subnet 10.1.35.1/24

$ kubectl get node -o wide
NAME                            STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ip-172-31-26-174.ec2.internal   Ready       68m   v1.23.4   172.31.26.174   54.209.207.221   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-42-12.ec2.internal    Ready       67m   v1.23.4   172.31.42.12    3.81.86.195      Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
ip-172-31-49-88.ec2.internal    Ready       69m   v1.23.4   172.31.49.88    54.160.123.197   Ubuntu 20.04.4 LTS   5.11.0-1028-aws   containerd://1.5.5
</pre>
<h2>アップグレード</h2>
<p>この節では、Charmed Kubernetes のマスタノードとワーカーノードのアップグレード方法を説明します。その他のコンポーネント containerd、easyrsa、etcd、flannel、kubeapi-load-balancer については、<a href="https://ubuntu.com/kubernetes/docs/upgrading">ドキュメント</a>を参照してください。</p>
<p>Charmed Kubernetes のワーカーノードをアップグレードするために、2つの方法があります。</p>
<ul>
<li><strong>Blue-green アップグレード</strong>: この方法では一時的により多くのリソースを利用しますが、一番安全でダウンタイムのないアップグレードを行えます。</li>
<li><strong>In-place アップグレード</strong>: この方法では既存のノードのアップグレードを行い、追加のリソースは必要ありませんが、サービスの停止が発生します。</li>
</ul>
<p>本番環境で利用する場合は、Blue-green アップグレードを推奨します。</p>
<p>ここでは、Blue-green アップグレードを利用したワーカーノードのアップグレードを検証してみます。</p>
<p>アップグレードする前に、Charmed Kubernetes が対応している Kubernetes の<a href="https://ubuntu.com/kubernetes/docs/supported-versions">バージョン情報</a>を確認します。今回は v1.21 の Charmed Kubernetes を v1.23 にアップグレードします。</p>
<p>検証用の Kubernetes クラスタをデプロイします。</p>
<pre>$ wget https://raw.githubusercontent.com/charmed-kubernetes/bundle/master/releases/1.21/bundle.yaml
$ juju deploy ./bundle.yaml</pre>
<p>マスタノードとワーカーノードのバージョンを確認します。</p>
<pre>$ juju status
...
App                    Version   Status       Scale  Charm                  Store       Channel   Rev  OS      Message
containerd             go1.13.8  active           5  containerd             charmstore  stable    146  ubuntu  Container runtime available
easyrsa                3.0.1     active           1  easyrsa                charmstore  stable    395  ubuntu  Certificate Authority connected.
etcd                   3.4.5     active           3  etcd                   charmstore  stable    607  ubuntu  Healthy with 1 known peer
flannel                0.11.0    active           3  flannel                charmstore  stable    571  ubuntu  Flannel subnet 10.1.78.1/24
kubeapi-load-balancer  1.18.0    active           1  kubeapi-load-balancer  charmstore  stable    814  ubuntu  Loadbalancer ready.
kubernetes-master      1.21.9    active           2  kubernetes-master      charmstore  stable   1034  ubuntu  Restarting snap.kube-proxy.daemon service
kubernetes-worker      1.21.9    active           3  kubernetes-worker      charmstore  stable    788  ubuntu  Waiting for kube-proxy to start.

$ juju scp kubernetes-master/0:config ~/.kube/config
$ kubectl get node
NAME               STATUS   ROLES    AGE    VERSION
ip-172-31-1-0      Ready    &lt;none&gt;   3m1s   v1.21.9
ip-172-31-44-16    Ready    &lt;none&gt;   3m9s   v1.21.9
ip-172-31-92-202   Ready    &lt;none&gt;   3m6s   v1.21.9</pre>
<p>まず、kubeapi-load-balancer をアップグレードします。</p>
<pre>$ juju upgrade-charm kubeapi-load-balancer</pre>
<p>次に、マスタノードをアップグレードします。以下のようにバージョンを指定して、upgrade を実行すると、マスタノードのアップグレードが始まります。</p>
<pre>$ juju upgrade-charm kubernetes-master
$ juju config kubernetes-master channel=1.23/stable

$ juju run-action kubernetes-master/0 upgrade
$ juju run-action kubernetes-master/1 upgrade</pre>
<p>最後に、ワーカーノードをアップグレードします。ワーカーノードのアップグレードを検証するために、アプリケーションをデプロイします。</p>
<pre>$ kubectl create deployment --image=nginx nginx
$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP          NODE              NOMINATED NODE   READINESS GATES
nginx-74d589986c-d8gqr   1/1     Running   0          6m51s   10.1.30.2   ip-172-31-30-80              
</pre>
<p>ワーカーノードのバージョンを設定します。</p>
<pre>$ juju upgrade-charm kubernetes-worker
$ juju config kubernetes-worker channel=1.23/stable</pre>
<pre>$ kubectl get node
NAME               STATUS   ROLES    AGE   VERSION
ip-172-31-14-158   Ready    &lt;none&gt;   25m   v1.21.9
ip-172-31-30-80    Ready    &lt;none&gt;   25m   v1.21.9
ip-172-31-64-109   Ready    &lt;none&gt;   23m   v1.21.9</pre>
<p>新たにワーカーノードを3つ追加します。新しく追加されるワーカーノードは新しいバージョンで作成されます。</p>
<pre>$ juju add-unit kubernetes-worker -n 3</pre>
<pre>$ kubectl get node
NAME               STATUS   ROLES    AGE     VERSION
ip-172-31-14-158   Ready    &lt;none&gt;   44m     v1.21.9
ip-172-31-30-80    Ready    &lt;none&gt;   44m     v1.21.9
ip-172-31-46-231   Ready    &lt;none&gt;   70s     v1.23.4
ip-172-31-46-47    Ready    &lt;none&gt;   4m58s   v1.23.4
ip-172-31-64-109   Ready    &lt;none&gt;   42m     v1.21.9
ip-172-31-81-150   Ready    &lt;none&gt;   2m13s   v1.23.4
</pre>
<p>旧バージョンのワーカーノードを一時停止します。</p>
<pre>$ juju run-action kubernetes-worker/0 pause
$ juju run-action kubernetes-worker/1 pause
$ juju run-action kubernetes-worker/2 pause</pre>
<p>すると、Nginx の Pod が新バージョンのワーカーノードに移動されます。</p>
<pre>$ kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP          NODE               NOMINATED NODE   READINESS GATES
nginx-deployment-74d589986c-d8gqr   1/1     Running   0          17m     10.1.30.2   ip-172-31-81-150              
</pre>
<p>これで、旧バージョンのワーカーノード安全に削除することができます。</p>
<pre>$ juju remove-unit kubernetes-worker/0
$ juju remove-unit kubernetes-worker/1
$ juju remove-unit kubernetes-worker/2

$ kubectl get node
NAME               STATUS   ROLES    AGE   VERSION
ip-172-31-46-231   Ready    &lt;none&gt;   22m   v1.23.4
ip-172-31-46-47    Ready    &lt;none&gt;   26m   v1.23.4
ip-172-31-81-150   Ready    &lt;none&gt;   24m   v1.23.4

$ juju status
App                    Version   Status  Scale  Charm                  Store       Channel  Rev   OS      Message
containerd             go1.13.8  active  4      containerd             charmstore  stable   200   ubuntu  Container runtime available
easyrsa                3.0.1     active  1      easyrsa                charmstore  stable   441   ubuntu  Certificate Authority connected.
etcd                   3.4.5     active  1      etcd                   charmstore  stable   655   ubuntu  Healthy with 1 known peer
flannel                0.11.0    active  4      flannel                charmstore  stable   619   ubuntu  Flannel subnet 10.1.66.1/24
kubeapi-load-balancer  1.18.0    active  1      kubeapi-load-balancer  charmstore  stable   866   ubuntu  Loadbalancer ready.
kubernetes-master      1.23.4    active  1      kubernetes-master      charmstore  stable   1106  ubuntu  Kubernetes master running.
kubernetes-worker      1.23.4    active  3      kubernetes-worker      charmstore  stable   838   ubuntu  Kubernetes worker running.</pre>
<h2>モニタリング</h2>
<p>Charmed Kubernetes では Prometheus によるモニタリング機能が利用可能です。</p>
<p>Kubernetes では Prometheus を利用した監視がよく使われています。Prometheus がクラスタの各種メトリクスを収集し、Grafana と連携して、Grafana のダッシュボードで Kubernetes クラスタとクラスタ上で動作するアプリケーションを監視することができます。</p>
<p>Prometheus によるモニタリング機能を利用するために、Bundleファイルをダウンロードし、デプロイ時に <code>--overlay</code> オプションに指定します。</p>
<pre>$ wget https://raw.githubusercontent.com/charmed-kubernetes/bundle/master/overlays/monitoring-pgt-overlay.yaml
$ juju deploy charmed-kubernetes --overlay monitoring-pgt-overlay.yaml</pre>
<p>prometheus、grafana、telegraf が起動していることを確認できます。</p>
<pre>$ juju status
Model  Controller      Cloud/Region   Version  SLA          Timestamp
k8s    k8s-controller  aws/us-east-1  2.9.22   unsupported  15:17:06+09:00

App                    Version   Status  Scale  Charm                  Store       Channel  Rev   OS      Message
containerd             go1.13.8  active  4      containerd             charmstore  stable   200   ubuntu  Container runtime available
easyrsa                3.0.1     active  1      easyrsa                charmstore  stable   441   ubuntu  Certificate Authority connected.
etcd                   3.4.5     active  1      etcd                   charmstore  stable   655   ubuntu  Healthy with 1 known peer
flannel                0.11.0    active  4      flannel                charmstore  stable   619   ubuntu  Flannel subnet 10.1.24.1/24
<strong>grafana                          active  1      grafana                charmhub    stable   51    ubuntu  Ready</strong>
kubeapi-load-balancer  1.18.0    active  1      kubeapi-load-balancer  charmstore  stable   866   ubuntu  Loadbalancer ready.
kubernetes-master      1.23.4    active  1      kubernetes-master      charmstore  stable   1106  ubuntu  Kubernetes master running.
kubernetes-worker      1.23.4    active  3      kubernetes-worker      charmstore  stable   838   ubuntu  Kubernetes worker running.
<strong>prometheus                       active  1      prometheus2            charmhub    stable   25    ubuntu  Ready</strong>
<strong>telegraf                         active  4      telegraf               charmhub    stable   44    ubuntu  Monitoring kubernetes-worker/1 (source version/commit 26e531a)</strong>
...</pre>
<p>以下のコマンドを実行し、Grafana の URL とログイン情報を取得します。</p>
<pre>$ juju run-action --wait grafana/0 get-login-info
unit-grafana-0:
  UnitId: grafana/0
  id: "4"
  results:
    password: 3cSfb2PshGHPLWJ4
    <strong>url: http://&lt;IP/ Address&gt;:3000/</strong>
    username: admin
  status: completed
...</pre>
<p>ブラウザから上記コマンドで確認した Grafana の URL に接続し、ログインします。Grafana のダッシュボードで Kubernetes クラスタ全体のリソースの使用状況などが確認できます。</p>
<p><img decoding="async" class="alignnone size-large wp-image-9022" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-1024x494.png" alt="" width="1024" height="494" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-1024x494.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-300x145.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-768x371.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-1536x742.png 1536w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-304x147.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring-282x136.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/02/charmed-kubernetes-monitoring.png 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h2>おわりに</h2>
<p>今回は Canonical Kubernetes ディストリビューション Charmed Kubernetes の特長、構築方法、スケーリング、アップグレード、モニタリング機能について紹介しましたが、いかがでしたでしょうか。</p>
<p>Juju というアプリケーションのデプロイツールを用いてオンプレミスでもコマンドを実行するだけで容易に Kubernetes 環境を構築できる Charmed Kubernetes は魅力的ではないでしょうか。</p>
<p><a href="https://www.sraoss.co.jp/tech-blog/kubernetes/charmed-kubernetes-persistent-volume">次回</a>はエンタープライズでの利用に欠かせない永続的ストレージについて説明します。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>マルチクラウド Kubernetes による PostgreSQL のディザスタリカバリ</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/multi-cloud-kubernetes-postgresql/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Wed, 30 Jun 2021 01:37:49 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Crunchy]]></category>
		<category><![CDATA[Operator]]></category>
		<category><![CDATA[ディザスタリカバリ]]></category>
		<category><![CDATA[マルチクラウド]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=7070</guid>

					<description><![CDATA[前回の Crunchy PostgreSQL Operatorの紹介 では、Kubernetes で PostgreSQL を運用するための Operator として Crunchy PostgreSQL Operato ...]]></description>
										<content:encoded><![CDATA[<p>前回の <a href="https://www.sraoss.co.jp/tech-blog/pgsql/crunchy-postgresql-operator/">Crunchy PostgreSQL Operatorの紹介 </a>では、Kubernetes で PostgreSQL を運用するための Operator として <a href="https://github.com/CrunchyData/postgres-operator">Crunchy PostgreSQL Operator</a> を紹介しました。</p>
<p>今回はマルチクラウド Kubernetes 構成に対応した Crunchy PostgreSQL Operator の高可用性とディザスタリカバリ (DR) について紹介します。</p>
<p><span id="more-7070"></span></p>
<h2>マルチクラウド Kubernetes とは</h2>
<p>マルチクラウド Kubernetes は特定の地域やクラウドサービスに依存せず、 複数のクラウドにまたがって Kubernetes クラスタをデプロイすることで、アプリケーションの可用性と耐障害性を向上させる構成です。</p>
<p>Kubernetes では Pod レベルもしくはノードレベルの障害を自動復旧させることはできますが、Kubernetes クラスタが所属している地域に災害が起きた場合、またはクラウドサービスが利用不能になった場合には、Kubernetes クラスタ全体がダウンしてしまいます。</p>
<p>マルチクラウド Kubernetes 構成を組むことで、一方の Kubernetes クラスタがダウンしても、別のクラスタでサービスを継続させることで、システムのダウンタイムを最小限に抑え、迅速に障害や災害から復旧することが可能になります。</p>
<p>しかし、複数の Kubernetes クラスタやクラウドをまたいでデータベースを管理し、データの同期を行うのは極めて困難です。Crunchy PostgreSQL Operator を利用することで、クラウド間で自動的にレプリケーションされている複数の PostgreSQL クラスタを容易に構築・運用できます。</p>
<h2>マルチクラウド Kubernetes に対応した Crunchy PostgreSQL Operator</h2>
<p>Crunchy PostgreSQL Operator は PostgreSQL インスタンスレベルの可用性を実現することもできますが、複数の Kubernetes クラスタにデプロイしている PostgreSQL クラスタを同期させ、クラスタ間でもフェイルオーバーさせることが可能です。さらに、複数の Kubernetes クラスタを物理的に独立した地域やクラウドに分散配置することでディザスタリカバリにも活用できます。</p>
<p>次の図は、Crunchy PostgreSQL Operator を用いたマルチクラウド Kubernetes の構成図になります。2つの独立した Kubernetes クラスタを異なるクラウドサービス、異なるリージョンに配置します。PostgreSQL クラスタをそれぞれの Kubernetes クラスタにデプロイし、アクティブ/スタンバイ構成で冗長化します。</p>
<p><img decoding="async" class="alignnone size-large wp-image-7139" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-1024x705.png" alt="Multi-Cloud アーキテクチャ" width="1024" height="705" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-1024x705.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-300x206.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-768x528.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-1536x1057.png 1536w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-304x209.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture-282x194.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/multi-cloud-architecture.png 1593w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>上記の構成図では、例として PostgreSQL アクティブクラスタを AWS に、スタンバイクラスタを GCP にデプロイしていますが、基本的には Crunchy PostgreSQL Operator が対応しているクラウド環境であれば、どの環境でも使用できます。また、オブジェクトストレージとしては S3 (もしくは S3と互換性のあるオブジェクトストレージ) と GCS のどちらでも利用できます。</p>
<p>上記構成の仕組みについて詳しく説明すると、</p>
<ul>
<li>PostgreSQL アクティブクラスタが定期的にバックアップと WAL アーカイブをオブジェクトストレージに保存します。</li>
<li>PostgreSQL スタンバイクラスタが継続的にオブジェクトストレージから WAL を読み込んで、PostgreSQL のアクティブ・スタンバイクラスタ間で同期を行います。</li>
<li>アクティブクラスタに障害が発生した場合は、手動でスタンバイクラスタをアクティブクラスタに昇格し、サービスを継続させることができます。</li>
<li>また、ダウンしていた旧アクティブクラスタは手動操作により、スタンバイクラスタとして復旧することも可能です。</li>
</ul>
<h2>検証環境</h2>
<p>本記事では、Crunchy PostgreSQL Operator を利用し、AWS と GCP を組み合わせたマルチクラウド環境で動作確認を行いました。検証環境の構成は以下の通りです。</p>
<ul>
<li>PostgreSQL アクティブクラスタ
<ul>
<li>Kubernetes クラスタ: EKS (AWS が提供するマネージド Kubernetes サービス)</li>
<li>リージョン: 東京リージョン</li>
</ul>
</li>
<li>PostgreSQL スタンバイクラスタ
<ul>
<li>Kubernetes クラスタ: GKE (Google が提供するマネージド Kubernetes サービス)</li>
<li>リージョン: 大阪リージョン</li>
</ul>
</li>
<li>オブジェクトストレージ
<ul>
<li>Amazon S3</li>
<li>リージョン: 東京リージョン</li>
</ul>
</li>
</ul>
<p>本記事では投稿時点での各ソフトウェアの最新バージョンを用いて以下の項目について動作確認を行いました。</p>
<ul>
<li>バージョン情報
<ul>
<li>Crunchy PostgreSQL Operator 4.7.0</li>
<li>PostgreSQL 13.3</li>
<li>Kubernetes 1.20</li>
</ul>
</li>
<li>動作確認項目
<ul>
<li>PostgreSQL アクティブクラスタのデプロイ</li>
<li>PostgreSQL スタンバイクラスタのデプロイ</li>
<li>クラスタ間レプリケーションの確認</li>
<li>PostgreSQL スタンバイクラスタの昇格</li>
<li>旧 PostgreSQL アクティブクラスタの復旧</li>
</ul>
</li>
</ul>
<p>なお、動作確認を行う前に、以下項目がすでに完了しているものとします。</p>
<ul>
<li>EKS クラスタの作成 (<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-cluster.html">こちら</a>を参照)</li>
<li>GKE クラスタの作成 (<a href="https://cloud.google.com/kubernetes-engine/docs/how-to?hl=ja">こちら</a>を参照)</li>
<li>Amazon S3 バケットの作成 (<a href="https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/creating-bucket.html">こちら</a>を参照)</li>
</ul>
<h2>PostgreSQL Operator および pgo のインストール・設定</h2>
<p>動作確認を行う前に、それぞれの Kubernetes クラスタにおいて、Crunchy PostgreSQL Operator および <code>pgo</code> クライアントコマンドのインストール・設定を行います。クラスタの切り替えは <code>kubectl config use-context &lt;クラスタ名&gt;</code> コマンドを使用します。クラスタの一覧は <code>kubectl config get-contexts<code> コマンドで確認できます。</code></code></p>
<p>まず、Amazon EKS クラスタに接続します。</p>
<p>Crunchy PostgreSQL Operator をインストールします。</p>
<pre>$ kubectl config use-context &lt;EKSクラスタ名&gt;
$ curl -LO https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.7.0/installers/kubectl/postgres-operator.yml
$ kubectl create namespace pgo
$ kubectl apply -f postgres-operator.yml</pre>
<p>pgo コマンドのインストール・設定を行います。本記事では、ローカル環境から各 Kubernetes クラスタに接続し、各種操作を行いますので、それぞれのクラスタに接続するための情報を $HOME/.pgo/eks と $HOME/.pgo/gke に格納します。</p>
<pre>$ curl -LO https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.7.0/installers/kubectl/client-setup.sh
$ chmod +x client-setup.sh
$ ./client-setup.sh
$ mv $HOME/.pgo/pgo/pgo /usr/local/bin/pgo
$ mv $HOME/.pgo/pgo $HOME/.pgo/eks
$ cat &gt;&gt; $HOME/env-eks &lt;&lt;EOF
export PGOUSER=$HOME/.pgo/eks/pgouser
export PGO_CA_CERT=$HOME/.pgo/eks/client.crt
export PGO_CLIENT_CERT=$HOME/.pgo/eks/client.crt
export PGO_CLIENT_KEY=$HOME/.pgo/eks/client.key
export PGO_APISERVER_URL='https://127.0.0.1:8443/'
export PGO_NAMESPACE=pgo
EOF
$ source $HOME/env-eks
$ kubectl -n pgo port-forward svc/postgres-operator 8443:8443 &amp;</pre>
<p>設定完了後、pgo コマンドを実行してみます。バージョン番号が表示されれば、正しく設定できています。</p>
<pre>$ pgo version
pgo client version 4.7.0
Handling connection for 8443
pgo-apiserver version 4.7.0</pre>
<p>次に、GKE クラスタに切り替えて、同様の設定を行います。</p>
<pre>$ kubectl config use-context &lt;GKEクラスタ名&gt;
$ kubectl create namespace pgo
$ kubectl apply -f postgres-operator.yml
$ ./client-setup.sh
$ mv $HOME/.pgo/pgo $HOME/.pgo/gke</pre>
<p>ローカルの 8443 ポートがすでにアクティブクラスタへの接続で使われていますので、スタンバイクラスタへの接続はローカルの 8444 ポートを使用します。</p>
<pre>$ cat &gt;&gt; $HOME/env-gke &lt;&lt;EOF
export PGOUSER=$HOME/.pgo/gke/pgouser
export PGO_CA_CERT=$HOME/.pgo/gke/client.crt
export PGO_CLIENT_CERT=$HOME/.pgo/gke/client.crt
export PGO_CLIENT_KEY=$HOME/.pgo/gke/client.key
export PGO_APISERVER_URL='https://127.0.0.1:8444/'
export PGO_NAMESPACE=pgo
EOF
$ source $HOME/env-gke
$ kubectl -n pgo port-forward svc/postgres-operator 8444:8443 &amp;</pre>
<p>正しく設定されているかを確認します。</p>
<pre>$ pgo version
pgo client version 4.7.0
Handling connection for 8444
pgo-apiserver version 4.7.0</pre>
<p>以上で、PostgreSQL Operator および pgo コマンドのインストール・設定が完了です。</p>
<p>ここからは、Crunchy PostgreSQL Operator を用いたマルチクラウド Kubernetes の動作確認を行います。</p>
<h2>PostgreSQL アクティブクラスタのデプロイ</h2>
<p>まず、EKS クラスタ上に、PostgreSQL アクティブクラスタをデプロイします。</p>
<pre>$ kubectl config use-context &lt;EKSクラスタ名&gt; &amp;&amp; source $HOME/env-eks
$ pgo create cluster hippo \
--replica-count=2 \
--pgbackrest-storage-type="s3" \
--pgbackrest-s3-bucket="crunchy-pg-backup" \
--pgbackrest-s3-region="ap-northeast-1" \
--pgbackrest-s3-endpoint="s3.ap-northeast-1.amazonaws.com" \
--pgbackrest-s3-key="XXXXXXXX" \
--pgbackrest-s3-key-secret="XXXXXXXXXXXXXXXXXXXXXXXXX" \
--password-superuser="postgres" \
--password-replication="postgres" \
--password="postgres"</pre>
<p>それぞれのオプションの意味は以下の通りです。</p>
<ul>
<li><strong><code>--replica-count</code></strong>: レプリカの数。2を指定すると、プライマリ1台、レプリカ2台がストリーミングレプリケーションを構成します。</li>
<li><strong><code>--pgbackrest-storage-type</code></strong>: バックアップと WAL アーカイブの保存先。s3 または gcs を指定します。Kubernetes の永続ボリュームにも保存したい場合は、local,s3 または local,gcs を指定します。</li>
<li><strong><code>--pgbackrest-s3-bucket</code></strong>: Amazon S3 の Bucket 名。</li>
<li><strong><code>--pgbackrest-s3-region</code></strong>: Amazon S3 のリージョン。</li>
<li><strong><code>--pgbackrest-s3-endpoint</code></strong>: Amazon S3 のエンドポイント。</li>
<li><strong><code>--pgbackrest-s3-key</code></strong>: アクセスキーID。</li>
<li><strong><code>--pgbackrest-s3-key-secret</code></strong>: シークレットアクセスキー。</li>
<li><strong><code>--password-superuser</code></strong>: postgres スーパーユーザのパスワード。</li>
<li><strong><code>--password-replication</code></strong>: レプリケーション用のユーザのパスワード。</li>
<li><strong><code>--password</code></strong>: クラスタ作成時に作られる一般ユーザのパスワード。</li>
</ul>
<p><code>--password-superuser</code> や<code>--password-replication</code>、<code>--password</code> にそれぞれのユーザのパスワードを指定します。指定しない場合はランダムに生成されます。ここでは、検証目的のため、すべてのユーザのパスワードを「postgres」と指定しています。</p>
<p>しばらくしたら、クラスタの状態を確認します。プライマリ、レプリカそれぞれの Pod (Instance) と Serviceが  UP 状態になっていれば、正常に起動できています。PostgreSQL アクティブクラスタが定期的に WAL アーカイブを S3 に転送します。</p>
<pre>$ pgo test hippo
cluster : hippo
Services
primary (10.100.113.239:5432): UP
replica (10.100.57.205:5432): UP
Instances
primary (hippo-7b8b78bf8f-2pd7c): UP
replica (hippo-fmju-7d7586ffcf-mlzxj): UP
replica (hippo-hyrz-789c4bb98c-fkgbf): UP</pre>
<h2>PostgreSQL スタンバイクラスタのデプロイ</h2>
<p>次に、GKE クラスタ上に、PostgreSQL スタンバイクラスタをデプロイします。PostgreSQL スタンバイクラスタが継続的に S3 から WAL を読み込み、変更を適用します。</p>
<pre>$ kubectl config use-context &lt;GKEクラスタ名&gt; &amp;&amp; source $HOME/env-gke
$ pgo create cluster hippo-standby \
--standby \
--replica-count=2 \
--pgbackrest-storage-type="s3" \
--pgbackrest-s3-bucket="crunchy-pg-backup" \
--pgbackrest-s3-region="ap-northeast-1" \
--pgbackrest-s3-endpoint="s3.ap-northeast-1.amazonaws.com" \
--pgbackrest-s3-key="XXXXXXXX" \
--pgbackrest-s3-key-secret="XXXXXXXXXXXXXXXXXXXXXXXXX" \
--pgbackrest-repo-path="/backrestrepo/hippo-backrest-shared-repo" \
--password-superuser="postgres" \
--password-replication="postgres" \
--password="postgres"</pre>
<p>それぞれのオプションの意味は以下の通りです。</p>
<ul>
<li><strong><code>--standby</code></strong>: スタンバイクラスタとして起動します。</li>
<li><strong><code>--replica-count</code></strong>: レプリカの数。2を指定すると、スタンバイ1台、レプリカ2台がカスケードレプリケーションを構成します。</li>
<li><strong><code>--pgbackrest-storage-type</code></strong>: アクティブクラスタのバックアップと WAL アーカイブの保存先。s3 または gcs を指定します。</li>
<li><strong><code>--pgbackrest-s3-bucket</code></strong>: Amazon S3 の Bucket 名。</li>
<li><strong><code>--pgbackrest-s3-region</code></strong>: Amazon S3 のリージョン。</li>
<li><strong><code>--pgbackrest-s3-endpoint</code></strong>: Amazon S3 のエンドポイント。</li>
<li><strong><code>--pgbackrest-s3-key</code></strong>: アクセスキーID。</li>
<li><strong><code>--pgbackrest-s3-key-secret</code></strong>: シークレットアクセスキー。</li>
<li><strong><code>--pgbackrest-repo-path</code></strong>: バックアップや WAL アーカイブを格納するディレクトリのパス。</li>
<li><strong><code>--password-superuser</code></strong>: アクティブクラスタで設定している postgres スーパーユーザのパスワード。</li>
<li><strong><code>--password-replication</code></strong>: アクティブクラスタで設定しているレプリケーション用のユーザのパスワード。</li>
<li><strong><code>--password</code></strong>: アクティブクラスタで設定している一般ユーザのパスワード。</li>
</ul>
<p><code>--password-superuser</code> や <code>--password-replication</code>、<code>--password</code> に指定しているパスワードとアクティブクラスタで指定しているパスワードが一致している必要があるので、注意してください。<br />
しばらくしたら、クラスタの状態を確認します。</p>
<pre>$ pgo test hippo-standby
cluster : hippo-standby
Services
primary (10.8.7.45:5432): UP
replica (10.8.2.146:5432): UP
Instances
primary (hippo-standby-5848d9d45c-j52n5): UP
replica (hippo-standby-eezm-b757c4d98-qt6pr): UP
replica (hippo-standby-jgom-5976f8bf8-lb54f): UP</pre>
<h2>レプリケーションの確認</h2>
<p>PostgreSQL アクティブ/スタンバイクラスタのデプロイが完了したら、クラスタ間でレプリケーションが正しく動作するかを確認します。</p>
<p>まず、アクティブクラスタのプライマリに接続し、データの更新を行います。</p>
<pre>$ kubectl config use-context &lt;EKSクラスタ名&gt; &amp;&amp; source $HOME/env-eks
$ kubectl port-forward svc/hippo 5432:5432 -n pgo &amp;

$ PASSWORD=$(kubectl get secret hippo-postgres-secret -n pgo -o 'jsonpath={.data.password}' | base64 -d)
$ PGPASSWORD=$PASSWORD psql -h 127.0.0.1 -U postgres
postgres=# create table t1 (id int);
postgres=# insert into t1 select generate_series(1,10);</pre>
<p>次に、スタンバイクラスタに接続し、データが同期されていることを確認します。</p>
<pre>$ kubectl config use-context &lt;GKEクラスタ名&gt; &amp;&amp; source $HOME/env-gke
$ kubectl port-forward svc/hippo-standby 5433:5432 -n pgo &amp;
$ PASSWORD=$(kubectl get secret hippo-standby-postgres-secret -n pgo -o 'jsonpath={.data.password}' | base64 -d)
$ PGPASSWORD=$PASSWORD psql -h 127.0.0.1 -U postgres -p 5433
postgres=# select * from t1;
id
----
1
2
3
4
5
6
7
8
9
10</pre>
<p>アクティブクラスタで行った更新がスタンバイクラスタに反映されているので、レプリケーションが正しく設定されていることがわかります。</p>
<h2>PostgreSQL スタンバイクラスタの昇格</h2>
<p>アクティブクラスタに障害が発生した場合、手動でスタンバイクラスタをアクティブクラスタに昇格することが可能です。</p>
<p>ここではアクティブクラスタを停止し、疑似的にクラスタ障害を起こします。</p>
<pre>$ kubectl config use-context &lt;EKSクラスタ名&gt; &amp;&amp; source $HOME/env-eks
$ pgo update cluster hippo --shutdown
WARNING: Are you sure? (yes/no): yes
Handling connection for 8443
updated pgcluster hippo</pre>
<p>スプリットブレイン状態にならないように、アクティブクラスタが完全に停止しているかを確認します。</p>
<pre>$ pgo test hippo
cluster : hippo
Services
Instances
primary (): DOWN</pre>
<p>アクティブクラスタが DOWN という状態になったら、スタンバイクラスタを昇格させます。</p>
<pre>$ kubectl config use-context &lt;GKEクラスタ名&gt; &amp;&amp; source $HOME/env-gke
$ pgo update cluster hippo-standby --promote-standby
Disabling standby mode will enable database writes for this cluster.
Please ensure the cluster this standby cluster is replicating from has been properly shutdown before proceeding!
WARNING: Are you sure? (yes/no): yes
Handling connection for 8444
updated pgcluster hippo-standby</pre>
<p>上記コマンドを実行すると、スタンバイクラスタがアクティブクラスタに昇格され、書き込みクエリ/読み取りクエリを処理できるようになります。</p>
<pre>$ PASSWORD=$(kubectl get secret hippo-standby-postgres-secret -n pgo -o 'jsonpath={.data.password}' | base64 -d)
$ PGPASSWORD=$PASSWORD psql -h 127.0.0.1 -U postgres -p 5433
postgres=# insert into t1 select generate_series(11,20);
INSERT 0 10</pre>
<p>スタンバイクラスタ昇格後、新しいタイムラインが生成され、新しいアクティブクラスタが定期的に WAL アーカイブを S3 に転送します。以下のコマンドで WAL アーカイブを格納するディレクトリの中身を確認できます。</p>
<pre>$ aws s3 ls --recursive s3://crunchy-pg-backup/backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/
2021-06-24 15:45:48 1861462 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000001-f8f3f3cf686b527c734c658cd6225294e708d398.gz
2021-06-24 15:46:47 16882 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000002-b354378ca96866d80fb0ce5dde0bc20e5e97811c.gz
2021-06-24 15:47:22 370 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000002.00000028.backup
2021-06-24 15:47:22 16834 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000003-d19c52e43342f0677293844fce0e9763bd4dc0fd.gz
2021-06-24 15:49:21 16936 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000004-e4353d933eee841030b4a644d457645510501e38.gz
2021-06-24 15:51:22 16461 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000005-f3692f7a98b733e2a16db695d03d85ec7e36a76a.gz
2021-06-24 16:23:28 38823 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000006-54001cf223598aaa70dab09817a960c77186712a.gz
2021-06-24 16:26:27 16457 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000100000000/000000010000000000000007-768ad2fa8f6a87db51bf0a7e199341a93f7839d7.gz
2021-06-24 17:13:36 41 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/00000002.history
2021-06-24 17:13:55 16518 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000200000000/000000020000000000000008-edfd6aae39a79700c091d0be5786fb322288f2cc.gz
2021-06-24 17:14:01 16479 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000200000000/000000020000000000000009-d43396f9558ba42ed492f3085d93edf3d995891f.gz
2021-06-24 17:14:02 370 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000200000000/000000020000000000000009.00000028.backup
2021-06-24 17:16:02 18147 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000200000000/00000002000000000000000A-5732b47a4a1a9a7069f567a5e8379104cfe2c32e.gz
2021-06-24 17:19:02 16462 backrestrepo/hippo-backrest-shared-repo/archive/db/13-1/0000000200000000/00000002000000000000000B-298ede92cecd0d1a1dd09852660c1164f9e73b69.gz</pre>
<h2>旧 PostgreSQL アクティブクラスタの復旧</h2>
<p>Kubernetes クラスタが障害から回復したら、ダウンしていた PostgreSQL アクティブクラスタをスタンバイクラスタとして復旧させることも可能です。<br />
以下のコマンドを実行し、PostgreSQL クラスタをスタンバイクラスタとして起動します。以下のコマンドを実行すると、既存の PVC が削除され、再作成されます。永続ボリュームを残したい場合は、利用している StorageClass の reclaimPolicy を Retain に設定してください。</p>
<pre>$ kubectl config use-context &lt;EKSクラスタ名&gt; &amp;&amp; source $HOME/env-eks
$ pgo update cluster hippo --enable-standby
Enabling standby mode will result in the deltion of all PVCs for this cluster!
Data will only be retained if the proper retention policy is configured for any associated storage
classes and/or persistent volumes.
Please proceed with caution.
WARNING: Are you sure? (yes/no): yes
Handling connection for 8443
updated pgcluster hippo</pre>
<p>ConfigMap からスタンバイクラスタとして設定されていることを確認できます。</p>
<pre>$ kubectl get cm hippo-config -n pgo -o yaml | grep standby
archive-get %f \"%p\""},"use_pg_rewind":true,"use_slots":false},"<strong>standby_cluster</strong>":{"create_replica_methods":["pgbackrest_standby"],"restore_command":"source</pre>
<p>上記設定を確認できたら、スタンバイクラスタを起動します。</p>
<pre>$ pgo update cluster hippo --startup
WARNING: Are you sure? (yes/no): yes
Handling connection for 8443
updated pgcluster hippo</pre>
<p>正常に起動していることを確認します。</p>
<pre>$ pgo test hippo
cluster : hippo
Services
primary (10.100.113.239:5432): UP
replica (10.100.57.205:5432): UP
Instances
primary (hippo-7b8b78bf8f-kdhk4): UP
replica (hippo-fmju-7d7586ffcf-5kxw5): UP
replica (hippo-hyrz-789c4bb98c-l2c4w): UP</pre>
<p>PVC の状態を確認します。「AGE」から PVC が再作成されていることがわかります。</p>
<pre>$ kubectl get pvc -n pgo
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   <strong>AGE</strong>
hippo             Bound    pvc-51b396c1-7204-45ed-9a03-5542a77dda8f   1Gi        RWO            gp2            <strong>1m40s</strong>
hippo-fmju        Bound    pvc-5223e924-abdb-45a9-bd05-cf4c4ecc4dbd   1Gi        RWO            gp2            <strong>1m40s</strong>
hippo-hyrz        Bound    pvc-fadc8764-1b7c-4004-8c69-70afe9f5142f   1Gi        RWO            gp2            <strong>1m39s</strong>
hippo-pgbr-repo   Bound    pvc-48d60253-4928-4bd3-967a-727d61c71d7d   1Gi        RWO            gp2            <strong>1m39s</strong></pre>
<h2>マルチクラウド Kubernetes の運用</h2>
<p>マルチクラウド Kubernetes 構成では、S3/GCS を介して PostgreSQL アクティブ/スタンバイクラスタがデータの同期を行っていますので、WAL アーカイブが行われる間隔 <code>archive_timeout</code> の設定値が大きすぎると、スタンバイクラスタに適用されるまで大きな遅延が発生する可能性がありますので、運用方針に合わせて設定値を調整してください。Crunchy PostgreSQL Operator のデフォルト値は <code>archive_timeout = 60</code> となります。</p>
<p>また、すでに運用している単一 Kubernetes クラスタをマルチクラスタ構成に変更することも可能です。S3/GCS にベースバックアップおよびベースバックアップ取得後の WAL アーカイブがあれば、いつでも PostgreSQL スタンバイクラスタを追加できます。</p>
<h2>終わりに</h2>
<p>今回は、Crunchy PostgreSQL Operator を用いて複数のクラウドサービス、複数のリージョンにまたがって PostgreSQL を冗長化する方法、障害時の復旧、運用の注意点などについて紹介しました。マルチクラウド Kubernetes 構成により、迅速に障害や災害から復旧することが可能になります。PostgreSQL の高可用性や災害対策を検討する際に、マルチクラウド Kubernetes が1つの有効な選択肢になるでしょう。</p>
<p>本記事の執筆時点では、障害発生時に自動的にスタンバイクラスタを昇格させる機能がなく、手動操作によりフェイルオーバーさせる必要がありますが、開発元が積極的に機能追加を行っており、今後の機能拡張が期待できます。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Zalando Postgres Operatorの紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/zalando-postgres-operator/</link>
		
		<dc:creator><![CDATA[山本 博之 (Hiroyuki Yamamoto)]]></dc:creator>
		<pubDate>Tue, 20 Oct 2020 03:37:07 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Zalando]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=6094</guid>

					<description><![CDATA[本記事では、コンテナ管理ツールのKubernetes上でPostgreSQLのHAクラスタを構築できるZalando Postgres Operatorについて解説します。 Zalando Postgres Operat ...]]></description>
										<content:encoded><![CDATA[<p>本記事では、コンテナ管理ツールのKubernetes上でPostgreSQLのHAクラスタを構築できるZalando Postgres Operatorについて解説します。</p>
<p><span id="more-6094"></span></p>
<h2>Zalando Postgres Operatorとは</h2>
<p><a href="https://github.com/zalando/postgres-operator">Zalando Postgres Operator</a> (以下 Postgres Operator)は、コンテナの管理ツールである<a href="https://kubernetes.io/">Kubernetes</a>上でHA構成のPostgreSQLクラスタを容易に構築できるようにするoperatorです(operatorはKubernetesの機能を拡張するプラグインのような機構です)。本ソフトウェアはドイツのファッション系eコマース企業である<a href="https://www.zalando.se/">Zalando SE</a>によって開発され、自社のサービスで運用されています。本ソフトウェアはMITライセンスの元公開されています。</p>
<h3>Operatorについて</h3>
<p>OperatorはKubernetes上で動作するアプリケーションの各種管理を自動化するための機能です。従来システム管理者が手動で行っていた、監視、障害時の対応、バックアップ、スケーリングといった様々な操作をプログラムとして記述し、Kubernetesに組み込むことでKubernetesの動作を拡張できます。</p>
<p>また、PostgreSQLに新たなoperatorが必要となるもう一つの要因として、PostgreSQLクラスタはプライマリとレプリカ(スタンバイ)の役割を考慮する必要があり、ステートレスなアプリケーション(例:Webサーバ)のように簡単にレプリカ(複製)を複数台用意することができないことが挙げられます。</p>
<h3>Postgres Operatorの機能</h3>
<p>Postgres Operatorによりストリーミングレプリケーションを用いたプライマリ1台、レプリカ(スタンバイ)複数台のPostgreSQLクラスタを簡単に構築することができます。</p>
<figure id="attachment_6097" aria-describedby="caption-attachment-6097" style="width: 1111px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-6097" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1.png" alt="" width="1111" height="557" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1.png 1111w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1-300x150.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1-1024x513.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1-768x385.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1-304x152.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_arch_1-282x141.png 282w" sizes="auto, (max-width: 1111px) 100vw, 1111px" /><figcaption id="caption-attachment-6097" class="wp-caption-text">Zalando Postgres Operatorの構成</figcaption></figure>
<p>Postgres Operatorの主な機能は以下になります。</p>
<ul>
<li>PostgreSQL HAクラスタの管理</li>
<li>ストリーミングレプリケーション (同期・非同期)</li>
<li>コネクションプール (PgBouncer使用)</li>
<li>フェイルオーバー (pg_rewindにより高速な復旧が可能)</li>
<li>ローリングアップデート</li>
<li>論理バックアップ (S3使用)</li>
<li>WALアーカイブ・PITR (WAL-E、S3使用)</li>
</ul>
<h3>Zalando社による講演</h3>
<p>PGCon 2020カンファレンスイベントにてZalando社により行われた講演の資料が公開されています。こちらもあわせて参照ください。<br />
<a href="https://www.pgcon.org/events/pgcon_2020/schedule/session/106-postgresql-on-k8s-at-zalando-two-years-in-production/">PostgreSQL on K8s at Zalando: Two years in production</a></p>
<h2>検証環境</h2>
<p>本記事ではKubernetesのマネージドサービスである<a href="https://aws.amazon.com/jp/eks/">Amazon EKS</a>上でZalando Postgres Operatorを動作させます。<br />
本記事では以下の構成で解説を行います。</p>
<ul>
<li>Kubernetes: Amazon EKS (Kubernetesのマネージドサービス)</li>
<li>ワーカーノード: t3.medium 2ノード</li>
<li>アーカイブ用ストレージ: Amazon S3</li>
<li>作業環境: CentOS 8.1 (VirtualBox上のVM)</li>
</ul>
<p>なお、EKSクラスタの作成は既に完了しているものとします。EKSの使用方法については<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/what-is-eks.html">こちら</a>を参照ください。</p>
<h2>検証内容</h2>
<p>今回はPostgres Operatorの以下の項目について確認しました。</p>
<ul>
<li>Postgres Operator のデプロイ</li>
<li>Web UI</li>
<li>PostgreSQL クラスタの作成</li>
<li>PostgreSQLの動作確認</li>
<li>フェイルオーバー</li>
<li>スケーリング</li>
<li>ローリングアップグレード</li>
<li>論理バックアップ</li>
<li>WALアーカイブ・PITR</li>
<li>ログ</li>
</ul>
<h2>Postgres Operatorのデプロイ</h2>
<p>Postgres OperatorはKubernetesとしては基本的な構成のため、導入は比較的簡単です。</p>
<p>Githubのリポジトリを作業環境にcloneします(もしくはtarballを展開します)。</p>
<pre>$ git clone https://github.com/zalando/postgres-operator.git
$ cd postgres-operator/</pre>
<p>グローバルな設定はconfigmap.yamlファイルに記述されているので、必要に応じて修正します。<br />
ここではバックアップ先のS3の設定などのグローバルな設定を記述します。</p>
<p>kubectl create -fで各YAMLファイルを適用していきます。</p>
<pre>$ kubectl create -f configmap.yaml
$ kubectl create -f operator-service-account-rbac.yaml
$ kubectl create -f postgres-operator.yaml
$ kubectl create -f api-service.yaml</pre>
<p>オブジェクトが作成され、正常に動作していることを確認します。</p>
<pre>$ kubectl get all
NAME                                     READY   STATUS    RESTARTS   AGE
pod/postgres-operator-85978df8cf-zqwjd   1/1     Running   0          48s

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/kubernetes          ClusterIP   10.100.0.1       &lt;none&gt;        443/TCP    168m
service/postgres-operator   ClusterIP   10.100.197.174   &lt;none&gt;        8080/TCP   22s

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/postgres-operator   1/1     1            1           48s

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/postgres-operator-85978df8cf   1         1         1       49s</pre>
<h2>Web UI</h2>
<p>Postgres OperatorにはWeb UIが同梱されており、ブラウザから以下の操作が可能です。</p>
<ul>
<li>クラスタの作成・削除</li>
<li>複製</li>
<li>設定編集</li>
<li>状態確認</li>
</ul>
<figure id="attachment_6099" aria-describedby="caption-attachment-6099" style="width: 1383px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-6099" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI.png" alt="" width="1383" height="944" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI.png 1383w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI-300x205.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI-1024x699.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI-768x524.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI-304x208.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/Screenshot_2020-06-25-PostgreSQL-Operator-UI-282x192.png 282w" sizes="auto, (max-width: 1383px) 100vw, 1383px" /><figcaption id="caption-attachment-6099" class="wp-caption-text">Postgres Operator UI</figcaption></figure>
<p>Web UIのデプロイは同様にkubectlを使用して行います。</p>
<pre>$ kubectl create -f ui/manifests/</pre>
<h2>Postgresクラスタの作成</h2>
<p>PostgresクラスタのデプロイはYAMLファイルを作成して適用するか、前述のWeb UIで作成操作を行います。</p>
<p>サンプルのYAMLファイルが同梱されていますので、それを元に設定ファイルを作成します。</p>
<ul>
<li>minimal-postgres-manifest.yaml: 最小限の設定</li>
<li>complete-postgres-manifest.yaml: 各種設定を網羅</li>
<li>standby-manifest.yaml: スタンバイ専用クラスタ設定</li>
</ul>
<p>基本的な設定を含む設定ファイルは以下になります。</p>
<pre>apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: sraoss-minimal-cluster           # クラスタ名の指定
spec:
  teamId: "sraoss"
  volume:
    size: 1Gi                            # ボリュームサイズの指定
  numberOfInstances: 2                   # インスタンス数(マスター+レプリカ)の指定
  users:                                 # DBユーザーの作成
    zalando:  # database owner
    - superuser
    - createdb
    foo_user: []  # role for application foo
  databases:                             # データベースの作成
    foo: zalando  # dbname: owner
  preparedDatabases:
    bar: {}
  postgresql:
    version: "12"                        # PostgreSQLバージョンの指定(9.6～12)
  enableLogicalBackup: true              # 論理バックアップの有効化
  logicalBackupSchedule: "30 00 * * * *" # cron形式のバックアップスケジュール
  enableConnectionPooler: true           # コネクションプールの有効化
  connectionPooler:
    numberOfInstances: 2</pre>
<p>これに加え、PostgreSQLのpostgresql.conf、pg_hba.confに相当する追加の設定を行うこともできます。</p>
<pre>...
  postgresql:
    version: "12“
    parameters:                          # postgresql.conf内のパラメータの指定
      shared_buffers: "64MB"
      max_connections: "50"
      log_statement: "all“
  patroni:
    initdb:                              # initdb時のパラメータの指定
      encoding: "UTF8"
      locale: "ja_JP.UTF-8"
      data-checksums: "true"
    pg_hba:                              # pg_hba.conf内のパラメータの指定
    - hostssl all all 0.0.0.0/0 md5
    - host    all all 0.0.0.0/0 md5</pre>
<p>同様にkubectlで適用します。</p>
<pre>$ kubectl create -f test-postgres-manifest.yaml</pre>
<p>クラスタの状態を確認します。numberOfInstances: 2の場合は2つのPodが作成されます。各Podがmasterかreplicaかはspilo-roleラベルで確認できます。</p>
<pre>$ kubectl get postgresql
NAME                     TEAM     VERSION   PODS   VOLUME   CPU-REQUEST   MEMORY-REQUEST   AGE    STATUS
sraoss-minimal-cluster   sraoss   12        2      1Gi                                     113s   Running

$ kubectl get pods -l application=spilo -L spilo-role
NAME                       READY   STATUS    RESTARTS   AGE     SPILO-ROLE
sraoss-minimal-cluster-0   1/1     Running   0          2m19s   master
sraoss-minimal-cluster-1   1/1     Running   0          95s     replica</pre>
<h2>PostgreSQLの動作確認</h2>
<p>Kubernetesクラスタ内の他のPodからは上記のmasterおよびreplicaにアクセスすることができます。</p>
<p>作業環境からpsqlでアクセスしたい場合はkubectlのport-forward機能を利用します。<br />
※ PGMASTERにはmasterのPod名が入ります。</p>
<pre>$ export PGMASTER=$(kubectl get pods -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=sraoss-minimal-cluster,spilo-role=master)
$ kubectl port-forward $PGMASTER 6432:5432</pre>
<p>別端末からlocalhost:6432に接続します。なお、接続時にはSSLが必須となります。<br />
※ パスワードはPostgresクラスタ作成時に自動生成されます。</p>
<pre>$ kubectl get secret postgres.sraoss-minimal-cluster.credentials -o 'jsonpath={.data.password}' | base64 -d
(パスワード文字列が表示される)
$ export PGSSLMODE=require
$ psql -U postgres -h localhost -p 6432
ユーザ postgres のパスワード:(上記パスワード文字列)
postgres=# create table t (t text); postgres=# insert into t values ('hoge'); postgres=# select * from t; t ------ hoge (1 行)</pre>
<h2>フェイルオーバー</h2>
<p>masterのPodに故障が発生した場合は、自動的にフェイルオーバーしてreplicaがmasterに昇格します。これはPostgres Operatorが使用している、SpiloというPostgreSQLおよびHAを実現するためのテンプレート(Patroni)を含むDockerイメージにより実現しています。</p>
<p>master Podを削除した場合は元replicaがmasterに昇格し、削除したPodが再作成されてreplicaとして復帰します。データサイズが少ない状態ではあるものの、フェイルオーバーは数10秒程度ですばやく完了します。</p>
<pre>$ kubectl delete pod sraoss-minimal-cluster-0
pod "sraoss-minimal-cluster-0" deleted

$ kubectl get pods -l application=spilo -L spilo-role
NAME                       READY   STATUS              RESTARTS   AGE   SPILO-ROLE
sraoss-minimal-cluster-0   0/1     ContainerCreating   0          6s
sraoss-minimal-cluster-1   1/1     Running             0          12m   master

$ kubectl get pods -l application=spilo -L spilo-role
NAME                       READY   STATUS    RESTARTS   AGE   SPILO-ROLE
sraoss-minimal-cluster-0   1/1     Running   0          23s   replica
sraoss-minimal-cluster-1   1/1     Running   0          12m   master</pre>
<p>masterのプロセス故障が発生した場合は元replicaがmasterに昇格し、元masterはPodを維持したままプロセスを再起動しreplicaに降格します。以下の例ではmaster Pod内に入り、initプロセスを停止させて疑似的にプロセス故障を起こしています。</p>
<pre>$ kubectl exec sraoss-minimal-cluster-0 -it /bin/sh
# kill 1</pre>
<h2>スケーリング</h2>
<p>デプロイ済みのPostgresクラスタの設定を変更すると、変更内容に応じてクラスタの状態を自動的に追従させます。<br />
クラスタのPodの数を指定するnumberOfInstancesを2から3に変更すると、Statefulsetsのレプリカ数も2から3に変更され、新しいreplica Podが起動します。</p>
<pre>$ kubectl edit postgresql
spec:
  <strong>numberOfInstances: 2 -&gt; 3 に修正</strong>

$ kubectl get postgresql
NAME                     TEAM     VERSION   PODS   VOLUME   CPU-REQUEST   MEMORY-REQUEST   AGE   STATUS
sraoss-minimal-cluster   sraoss   12        <strong>3</strong>      1Gi                                     53m   Running
$ kubectl get statefulsets
NAME                     READY   AGE
sraoss-minimal-cluster   <strong>3/3</strong>     14m
$ kubectl get po -l application=spilo -L spilo-role
NAME                       READY   STATUS    RESTARTS   AGE     SPILO-ROLE
sraoss-minimal-cluster-0   1/1     Running   0          50m     master
sraoss-minimal-cluster-1   1/1     Running   0          50m     replica
<span style="color: #0000ff;"><strong>sraoss-minimal-cluster-2   1/1     Running   0          7m21s   replica</strong></span></pre>
<h2>ローリングアップデート</h2>
<p>PostgreSQLのマイナーバージョンアップ(Dockerイメージの更新)、およびPostgreSQLの設定変更はローリングアップデートによりサービスの停止なしに行うことができます。なお、メジャーバージョンアップはローリングアップデートでは行えないため、ベースバックアップからクラスタの複製により行う必要があります。</p>
<figure id="attachment_6107" aria-describedby="caption-attachment-6107" style="width: 258px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="wp-image-6107 size-medium" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_rollupd-258x300.png" alt="" width="258" height="300" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_rollupd-258x300.png 258w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_rollupd-184x214.png 184w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_rollupd-224x260.png 224w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_rollupd.png 351w" sizes="auto, (max-width: 258px) 100vw, 258px" /><figcaption id="caption-attachment-6107" class="wp-caption-text">ローリングアップデート</figcaption></figure>
<p>以下、Dockerイメージを更新した場合にローリングアップデートが行われる様子を実際に確認してみます。</p>
<h3>Dockerイメージの更新</h3>
<pre>$ kubectl edit postgresql sraoss-test-cluster
  dockerImage: (旧Dockerイメージ) -&gt; (新Dockerイメージ)
  postgresql:
    version: "12"
</pre>
<h3>ローリングアップデート開始</h3>
<pre>$ kubectl get postgresql
NAME                  TEAM     VERSION   PODS   VOLUME   CPU-REQUEST   MEMORY-REQUEST   AGE     STATUS
sraoss-test-cluster   sraoss   12        2      1Gi                                     9m19s   <strong>Updating</strong>

$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS        RESTARTS   AGE     SPILO-ROLE
sraoss-test-cluster-0   1/1     Running       0          9m24s   master
sraoss-test-cluster-1   1/1     <strong>Terminating</strong>   0          8m42s

$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS              RESTARTS   AGE     SPILO-ROLE
sraoss-test-cluster-0   1/1     Running             0          9m34s   master
sraoss-test-cluster-1   0/1     <strong>ContainerCreating</strong>   0          8s</pre>
<h3>元replica Podが再作成され、masterに昇格</h3>
<pre>$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS    RESTARTS   AGE     SPILO-ROLE
sraoss-test-cluster-0   1/1     Running   0          9m39s
<strong>sraoss-test-cluster-1   1/1     Running   0          13s     promoted</strong></pre>
<h3>元master Podの再作成</h3>
<pre>$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS        RESTARTS   AGE     SPILO-ROLE
sraoss-test-cluster-0   1/1     <strong>Terminating</strong>   0          9m49s
sraoss-test-cluster-1   1/1     Running       0          23s     <strong>master</strong>

$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS              RESTARTS   AGE   SPILO-ROLE
sraoss-test-cluster-0   0/1     <strong>ContainerCreating</strong>   0          4s
sraoss-test-cluster-1   1/1     Running             0          30s   master</pre>
<h3>元master Podがreplicaとして復帰</h3>
<pre>$ kubectl get pods -l application=spilo -L spilo-role
NAME                    READY   STATUS    RESTARTS   AGE   SPILO-ROLE
<strong>sraoss-test-cluster-0   1/1     Running   0          14s   replica</strong>
sraoss-test-cluster-1   1/1     Running   0          40s   master</pre>
<h2>論理バックアップ</h2>
<p>Postgres Operatorでは定期的にAmazon S3に論理バックアップ(pg_dumpall)を取ることができます。なお、論理バックアップからの自動リストア機能はないので、リストアはクラスタ作成後手動で行う必要があります。</p>
<p>前述のconfigmap.yamlでバックアップ先のS3の設定を行います。</p>
<pre>logical_backup_s3_bucket: "zalando-backup"
logical_backup_s3_access_key_id: "xxxxxxxxxxxxxxxx"
logical_backup_s3_secret_access_key: "xxxxxxxxxxxxxxxx</pre>
<p>Postgresクラスタの設定で論理バックアップを有効にします。スケジュールはcron表記で指定します(以下は毎日0:30に実行)。</p>
<pre>  enableLogicalBackup: true
  logicalBackupSchedule: “30 00 * * *"</pre>
<p>指定時刻にKubernetesのCronJobとしてバックアップが実行されます。</p>
<pre>$ kubectl get cronjob
NAME                                    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
logical-backup-sraoss-minimal-cluster   30 00 * * *   False     0        6m48s           27m

$ kubectl get job
NAME                                               COMPLETIONS   DURATION   AGE
logical-backup-sraoss-minimal-cluster-1593418800   1/1           3s         6m46s

$ kubectl describe job logical-backup-sraoss-minimal-cluster-1593418800
...
Pods Statuses:  0 Running / 1 Succeeded / 0 Failed</pre>
<p>S3の以下の場所にバックアップファイルがアップロードされます。</p>
<pre>s3://&lt;bucket-name&gt;/spilo/&lt;cluster-name&gt;/&lt;UUID&gt;/logical_backups/&lt;job ID&gt;.sql.gz</pre>
<h2>WALアーカイブ・PITR</h2>
<p>前述のconfigmap.yamlでバックアップ先のS3の設定を行います。なお、EKSクラスタからS3 bucketへのアクセスが許可されている必要があります。</p>
<pre>wal_s3_bucket: "zalando-wal-backup"</pre>
<p>S3の以下の場所にWALがアーカイブされます。</p>
<pre>s3://&lt;bucket-name&gt;/spilo/&lt;cluster-name&gt;/&lt;UUID&gt;/wal/basebackups_00x/
s3://&lt;bucket-name&gt;/spilo/&lt;cluster-name&gt;/&lt;UUID&gt;/wal/wal_00x/</pre>
<p>S3のバックアップからクラスタを複製(clone)することでPITRが可能です。PITRの復元位置を指定することもできます。</p>
<pre>spec:
  clone:
    uid: "efd12e58-5786-11e8-b5a7-06148230260c"
    cluster: “sraoss-test-cluster"
    timestamp: "2017-12-19T12:40:33+01:00"</pre>
<figure id="attachment_6110" aria-describedby="caption-attachment-6110" style="width: 600px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="wp-image-6110" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone-300x91.png" alt="" width="600" height="183" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone-300x91.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone-768x234.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone-304x93.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone-282x86.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/zalando_wal_clone.png 974w" sizes="auto, (max-width: 600px) 100vw, 600px" /><figcaption id="caption-attachment-6110" class="wp-caption-text">WALアーカイブからのclone</figcaption></figure>
<h2>ログ</h2>
<p>Postges Operator自体はログ管理に関する機能を持ちません。Podのsidecarコンテナをユーザが追加することは可能なので、ログ収集のための補助コンテナを導入し、fluentdと連携するなどの作り込みは必要となります。また、Kubernetesクラスタのログを集約するKubernetes Log WatcherというツールがZalando社によって公開されています。</p>
<p>クラスタの各Podのログはkubectl logsコマンドにより確認できます。</p>
<pre>$ kubectl logs sraoss-minimal-cluster-0</pre>
<p>また、Pod内のPostgreSQLログは以下のように格納されています。</p>
<pre>/home/postgres/pgdata/pgroot/pg_log/
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-0.csv
-rw-r--r-- 1 postgres postgres 277783 Jun 29 06:58 postgresql-1.csv
-rw-r--r-- 1 postgres postgres    205 Jun 29 06:12 postgresql-1.log
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-2.csv
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-3.csv
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-4.csv
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-5.csv
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-6.csv
-rw-r--r-- 1 postgres postgres      0 Jun 29 06:12 postgresql-7.csv</pre>
<h2>おわりに</h2>
<p>手動でPostgreSQL HAクラスタを構築するとなるとかなりの手間がかかります。また、Kubernetes上にそれを構築しようとするのはかなり困難です。Zalando Postgres Operatorを用いることで、Kubernetes上のPostgreSQL HAクラスタの構築が非常に容易になります。実際に開発元のサービスで運用されている実績があり、機能的にまだ不十分なところもあるものの、フェイルオーバーなどの重要な機能に関してはしっかりと作り込まれていると感じました。今後の発展が楽しみなソフトウェアといえます。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Crunchy Postgres Operatorの紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/crunchy-postgresql-operator/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Tue, 20 Oct 2020 03:33:07 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Crunchy]]></category>
		<category><![CDATA[Crunchy Data]]></category>
		<category><![CDATA[Operator]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=6127</guid>

					<description><![CDATA[前回の記事Zalando Postgres Operatorの紹介ではKubernetes上でPostgreSQLのHAクラスタを構築するためのOperatorの1つZalando Postgres Operatorにつ ...]]></description>
										<content:encoded><![CDATA[<p>前回の記事<a href="https://www.sraoss.co.jp/tech-blog/pgsql/zalando-postgres-operator">Zalando Postgres Operatorの紹介</a>では<a href="https://kubernetes.io/">Kubernetes</a>上でPostgreSQLのHAクラスタを構築するためのOperatorの1つZalando Postgres Operatorについて解説しました。</p>
<p>今回の記事では、前回の記事に続いて<a href="https://github.com/CrunchyData/postgres-operator">Crunchy Postgres Operator</a>について解説します。</p>
<p><strong>本記事の説明は Crunchy Postgres Operator  4.7 を対象にします。2021 年にリリースされたバージョン 5 (v5) については<a href="https://www.sraoss.co.jp/tech-blog/kubernetes/crunchy-postgres-operator-v5/">Crunchy Postgres Operator v5 の紹介</a>を参照してください。</strong></p>
<p><span id="more-6127"></span></p>
<h2>Crunchy Postgres Operatorとは</h2>
<p><a href="https://github.com/CrunchyData/postgres-operator">Crunchy Postgres Operator</a>は、コンテナの管理ツールであるKubernetes上でPostgreSQL HAクラスタを容易に構築ためのOperatorの1つです(OperatorはKubernetesの機能を拡張するプラグインのような機構です)。Crunchy Postgres OperatorはPostgreSQLの関連サービスを提供しているアメリカの会社である<a href="https://www.crunchydata.com/">Crunchy Data</a>によって開発され、Apache License 2.0で公開されています。PostgreSQL 9.5以降に対応しています。</p>
<h3>全体構成図</h3>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-6541" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-1024x507.png" alt="" width="1024" height="507" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-1024x507.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-300x149.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-768x380.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-1536x761.png 1536w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-304x151.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture-282x140.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/10/architecture.png 1952w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<h3>Crunchy Postgres Operatorの機能</h3>
<p>Crunchy Postgres Operatorの主な機能は以下の通りです。</p>
<ul>
<li>PostgreSQL HAクラスタのデプロイ・管理</li>
<li>CLI (pgo)</li>
<li>ストリーミングレプリケーション (同期・非同期)</li>
<li>フェイルオーバー</li>
<li>バックアップ (S3対応)</li>
<li>WALアーカイブ (S3対応)</li>
<li>リストア・PITR</li>
<li>自動アップグレード</li>
<li>コネクションプール (PgBouncer使用)</li>
<li>PostgreSQLのログ解析</li>
<li>監視</li>
</ul>
<h2>検証環境</h2>
<p>本記事ではKubernetesのマネージドサービスである<a href="https://aws.amazon.com/jp/eks/">Amazon EKS</a>上でCrunchy Postgres Operatorの動作確認を行いました。<br />
環境の構成およびバージョン情報は以下の通りです。</p>
<ul>
<li>Crunchy Postgres Operator  4.7.0</li>
<li>Kubernetes: Amazon EKS (Kubernetesのマネージドサービス)</li>
<li>ワーカーノード: t3.medium 2ノード</li>
<li>アーカイブ用ストレージ: Amazon S3</li>
<li>作業環境: CentOS 7.6 (AWS上のEC2)</li>
</ul>
<p>なお、EKSクラスタの作成は既に完了しているものとします。EKSの使用方法については<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/what-is-eks.html">こちら</a>を参照ください。</p>
<h2>検証内容</h2>
<p>本記事は<a href="https://github.com/CrunchyData/postgres-operator/releases/tag/v4.7.0">Crunchy Postgres Operator 4.7.0</a>を用いて以下の項目について動作確認を行いました。</p>
<ul>
<li>Crunchy Postgres Operatorのデプロイ</li>
<li>pgoクライアントコマンドのインストール</li>
<li>PostgreSQLクラスタの作成</li>
<li>psql による接続確認</li>
<li>PostgreSQLの設定</li>
<li>フェイルオーバー</li>
<li>スケーリング</li>
<li>バックアップ</li>
<li>リストア・PITR</li>
<li>アップグレード</li>
</ul>
<h2>Crunchy Postgres Operatorのデプロイ</h2>
<p>以下の方法でPostgreSQL Operatorをデプロイできます。<br />
&#8211; Ansible<br />
&#8211; Bashスクリプト<br />
&#8211; pgo-deploy Job (※推奨、v4.3.0 ～)</p>
<p>v4.3.0から追加された「pgo-deploy Job」を用いたデプロイ方法は他の方法より簡単にPostgreSQL Operatorをインストール/アップデート/アンインストールできるため、こちらの方法の利用が推奨されています。</p>
<p>以下では「pgo-deploy Job」を用いたデプロイ方法を紹介します。</p>
<p>1. まず、デプロイの設定を記述したマニフェストを取得します。</p>
<pre>$ curl -LO https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.7.0/installers/kubectl/postgres-operator.yml</pre>
<p>2. 環境に合わせて、マニフェストを編集します。</p>
<p>最低限Operatorが利用するストレージの設定が必要になります。指定しない場合は、Amazon EKSデフォルトのストレージクラスを利用します。</p>
<p>デフォルトのストレージクラスが定義されていることを確認します。</p>
<pre>$ kubectl get sc
NAME           PROVISIONER            AGE
gp2 (default)  kubernetes.io/aws-ebs  5h49m</pre>
<p>3. デフォルトではOperatorがpgoというNamespaceにインストールされるため、<strong>pgo</strong>というNamespaceを作成し、マニフェストを適用します。</p>
<pre>$ kubectl create namespace pgo
$ kubectl apply -f postgres-operator.yml</pre>
<p>4. インストール後、PostgreSQL Operatorが正常にインストールされていることを確認します。</p>
<pre>$ kubectl get pod -n pgo
NAME                                 READY   STATUS      RESTARTS   AGE
pgo-deploy-bq9fs                     0/1     Completed   0          4m50s
postgres-operator-5d5ff486c7-jtdc6   4/4     Running     1          3m52s

$ kubectl get svc -n pgo
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
postgres-operator   ClusterIP   10.100.180.218   &lt;none&gt;        8443/TCP,4171/TCP,4150/TCP   19m</pre>
<p>5. 終了した 「pgo-deploy」Jobを削除するには以下のコマンドを実行します。</p>
<pre>$ kubectl delete -f postgres-operator.yml</pre>
<h2>pgoクライアントコマンドのインストール</h2>
<p>1. client-setup.shスクリプトをダウンロード・実行し、pgoクライアントをインストールします。</p>
<pre>$ curl -LO https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.7.0/installers/kubectl/client-setup.sh
$ chmod +x client-setup.sh
$ ./client-setup.sh</pre>
<p>2. 以下の環境変数を設定します。</p>
<pre>$ cat &gt;&gt; ~/.bashrc &lt;&lt;EOF 
export PATH="$HOME/.pgo/pgo:$PATH"
export PGOUSER="$HOME/.pgo/pgo/pgouser"
export PGO_CA_CERT="$HOME/.pgo/pgo/client.crt"
export PGO_CLIENT_CERT="$HOME/.pgo/pgo/client.crt"
export PGO_CLIENT_KEY="$HOME/.pgo/pgo/client.key"
export PGO_NAMESPACE=pgo
EOF
$ source ~/.bashrc</pre>
<p>3. インストール後、pgoクライアントが正常にインストールされていることを確認します。</p>
<p>postgres-operatorをローカルの8443へポートフォワードを行います。</p>
<pre>$ kubectl -n pgo port-forward svc/postgres-operator 8443:8443 &amp;
</pre>
<p>APIサーバの環境変数をローカルの8443ポートに設定します。</p>
<pre>$ cat &gt;&gt; ~/.bashrc &lt;&lt;EOF 
export PGO_APISERVER_URL="https://127.0.0.1:8443/"
EOF</pre>
<p>clientとAPIサーバのバージョン番号が表示されれば、正しくインストールできています。</p>
<pre>$ pgo version
pgo client version 4.7.0
Handling connection for 8443
pgo-apiserver version 4.7.0</pre>
<h2>PostgreSQLクラスタの作成</h2>
<p><strong>pgo create cluster</strong>コマンドを用いて PostgreSQLクラスタを作成します。</p>
<pre>$ pgo create cluster hippo --replica-count=1 --sync-replication</pre>
<p>上記コマンドで以下のような構成のクラスタが作成されます。</p>
<ul>
<li>primary 1台、replica 1台</li>
<li>同期レプリケーション</li>
<li>自動フェイルオーバー (デフォルト)</li>
<li>バックアップ (デフォルト)</li>
<li>WAL アーカイブ (デフォルト)</li>
<li>ローカルストレージにバックアップと WALアーカイブを保存 (デフォルト)</li>
</ul>
<p>postgresスーパーユーザのパスワードを設定したい場合は<strong><code>--password-superuser</code></strong>オプションで設定可能です。指定しない場合は自動生成されます。また、バックアップの保存先やサイドカー機能などのオプションの詳細については、後述する「バックアップ」や「サイドカー機能」を参照ください。</p>
<p>クラスタの状態を確認します。正常に起動できれば、primary、replicaそれぞれのPod (Instance)とServiceが<strong>UP</strong>状態になっています。</p>
<pre>$ pgo test hippo
Handling connection for 8443

cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                primary (hippo-646dfd49f5-lbc8l): UP
                replica (hippo-gfps-65f776cc6-mhdcw): UP</pre>
<h2>psql による接続確認</h2>
<p>Kubernetesクラスタ内のノードからは上記primary及びreplicaのServiceに接続することができます。<br />
作業環境からpsqlでprimary及びreplicaのServiceに接続したい場合はkubectlのport-forward機能を利用します。<br />
ここではprimary Serviceの5432ポートをローカルの5432へポートフォワードを行います。<br />
※ PGPRIMARYにはprimaryのService名が入ります。</p>
<pre>$ export PGPRIMARY=$(kubectl get svc -o jsonpath={.items..metadata.name} -l name=hippo,pg-cluster=hippo,vendor=crunchydata -n pgo)
$ kubectl -n pgo port-forward svc/$PGPRIMARY 5432:5432 &amp;</pre>
<p>psqlで接続します。<br />
接続時にパスワード入力プロンプトが表示されるため、クラスタ作成時に指定したパスワードを入力します。</p>
<pre>$ psql -h localhost -U postgres
ユーザ postgres のパスワード:
postgres=# select application_name, state, sync_state from pg_stat_replication;
      application_name      |   state   | sync_state 
----------------------------+-----------+------------
 hippo-gfps-65f776cc6-mhdcw | streaming | sync
(1 行)
</pre>
<p>クラスタ作成時にパスワードを設定していない場合はランダムに生成されています。生成されたパスワードは<strong>kubectl get secret</strong>コマンドで確認できます。</p>
<pre>$ kubectl get secret hippo-postgres-secret -n pgo -o 'jsonpath={.data.password}' | base64 -d</pre>
<h2>PostgreSQLの設定</h2>
<p>PostgreSQLのpostgresql.confやpg_hba.conf、pg_ident.conf などの設定はConfigMapで設定できます。<br />
事前に作成したConfigMapはクラスタ作成時に<strong><code>--custom-config</code></strong>オプションで適用可能です。<br />
指定しない場合は、クラスタ作成時に<strong>&lt;clusterName&gt;-pgha-config</strong>というConfigMapが作成されます。</p>
<p>ConfigMap &lt;clusterName&gt;-pgha-configは以下で構成されます。</p>
<ul>
<li>Distributed Configuration Store (DCS) : クラスタ全体の設定</li>
<li>local Database : PostgreSQLサーバごとの設定</li>
</ul>
<p><strong><code>kubectl describe configmap</code></strong>コマンドを用いてConfigMapの設定を確認できます。</p>
<pre>$ kubectl describe configmap hippo-pgha-config -n pgo</pre>
<p>設定を変更するには <code>kubectl edit configmap</code> コマンドを利用します。<br />
例えば、<code>log_statement</code>を<code>none</code>から<code>all</code>に変更するには以下のコマンドを実行します。<br />
変更するとOperatorによって変更が検出され、自動的にPostgreSQLに反映されます。</p>
<pre>$ kubectl edit configmap hippo-pgha-config -n pgo
data:
  hippo-dcs-config: |
    postgresql:
      parameters:
      ...
        <strong>log_statement: none -&gt; all に変更</strong></pre>
<p>ただし、PostgreSQLの再起動が必要になるパラメータもあり、再起動が必要かどうかは<strong><code>pgo restart hippo --query</code></strong>コマンドで確認できます。<br />
例えば、max_wal_sendersの設定値を変更した場合、PostgreSQLの再起動が必要になります。</p>
<pre>$ kubectl edit configmap hippo-pgha-config -n pgo
data:
  hippo-dcs-config: |
    postgresql:
      parameters:
      ...
        <strong>max_wal_senders: 6 -&gt; 8 に変更
</strong></pre>
<p>設定変更後<code>pgo restart hippo --query</code>を実行し、PENDING RESTARTカラムがtrueになっていれば、再起動が必要なことを意味しています。</p>
<pre>$ pgo restart hippo --query
Handling connection for 8443
Cluster: hippo
INSTANCE                ROLE            STATUS          NODE                                                       REPLICATION LAG         PENDING RESTART
hippo                   primary         running         ip-192-168-84-180.us-west-2.compute.internal               0 MB                    true
hippo-gfps              replica         running         ip-192-168-30-254.us-west-2.compute.internal               0 MB                    true</pre>
<p>上記結果より、hippo及びhippo-gfpsの再起動が必要なので、それぞれのPod (Instance)名を<strong><code>pgo restart</code></strong>コマンドの<strong><code>--target</code></strong>オプションに指定し、再起動します。</p>
<pre>$ pgo restart hippo --target hippo 
$ pgo restart hippo --target hippo-gfps</pre>
<h2>フェイルオーバー</h2>
<p>primaryのPodに故障が発生した場合は、自動的にフェイルオーバーしてreplicaがprimaryに昇格します。これはPostgreSQL HAのテンプレートであるPatroniを利用して実現しています。</p>
<h3>Podを削除した場合</h3>
<p>primaryのPodを削除した場合、replicaがprimary に昇格し、新たなreplicaが生成され、復旧します。<br />
replicaの生成は<a href="https://pgbackrest.org/">pgBackRest</a>のdelta restoreの機能で、迅速に復旧することができます。</p>
<pre>$ pgo test hippo
Handling connection for 8443
cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                primary (hippo-646dfd49f5-lbc8l): UP
                replica (hippo-gfps-65f776cc6-mhdcw): UP

$ kubectl delete pods hippo-646dfd49f5-lbc8l -n pgo
pod "hippo-646dfd49f5-lbc8l" deleted

$ pgo test hippo
Handling connection for 8443
cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                replica (hippo-646dfd49f5-x7m67): UP
                primary (hippo-gfps-65f776cc6-mhdcw): UP</pre>
<h3>プロセス障害の場合</h3>
<p>primaryの Podのプロセス障害が発生した場合は、replicaがprimaryに昇格し、<br />
旧primaryはPodを維持したままreplicaとして再起動します。<br />
以下の例ではPod内に入り、initプロセスを停止させて疑似的にプロセス障害を起こしています。</p>
<pre>$ kubectl exec hippo-gfps-65f776cc6-mhdcw -it -n pgo -- /bin/sh
$ kill 1

$ pgo test hippo
Handling connection for 8443
cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                primary (hippo-646dfd49f5-x7m67): UP
                replica (hippo-gfps-65f776cc6-mhdcw): UP</pre>
<h2>スケーリング</h2>
<p>PostgreSQLのreplicaのスケーリングンにより、データベースの負荷分散や耐障害性の向上を実現できます。<br />
pgoクライアントコマンドを実行することで、簡単にスケールアップ/スケールダウンが可能です。</p>
<h3>スケールアップ</h3>
<p>replicaを1台から2台に増やします。</p>
<pre>$ pgo scale hippo --replica-count=1
$ pgo test hippo
Handling connection for 8443
cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                primary (hippo-646dfd49f5-x7m67): UP
                replica (hippo-gfps-65f776cc6-mhdcw): UP
                replica (hippo-zdlq-69dcc59d9-8hn6f): UP</pre>
<h3>スケールダウン</h3>
<p>スケールダウン可能なreplicaを確認します。</p>
<pre>$ pgo scaledown hippo --query
Handling connection for 8443
Cluster: hippo
REPLICA   STATUS   NODE                                          REPLICATION LAG  PENDING RESTART
hippo-gfps running ip-192-168-30-254.us-west-2.compute.internal  0 MB             false
hippo-zdlq running ip-192-168-84-180.us-west-2.compute.internal  0 MB             false
</pre>
<p>replica「hippo-zdlq」を削除します。</p>
<pre>$ pgo scaledown hippo --target=hippo-zdlq

$ pgo test hippo
Handling connection for 8443
cluster : hippo
        Services
                primary (10.100.43.244:5432): UP
                replica (10.100.157.106:5432): UP
        Instances
                primary (hippo-646dfd49f5-x7m67): UP
                replica (hippo-gfps-65f776cc6-mhdcw): UP</pre>
<h2>バックアップ</h2>
<figure id="attachment_6161" aria-describedby="caption-attachment-6161" style="width: 938px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-6161" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup.png" alt="" width="938" height="461" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup.png 938w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup-300x147.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup-768x377.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup-304x149.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2020/07/backup-282x139.png 282w" sizes="auto, (max-width: 938px) 100vw, 938px" /><figcaption id="caption-attachment-6161" class="wp-caption-text">バックアップ</figcaption></figure>
<p>Crunchy Postgres Operatorのバックアップ/リストアは内部的に<a href="https://pgbackrest.org/">pgBackRest</a>のバックアップ/リストアユーティリティを利用しています。<br />
定期的にフルバックアップまたは差分バックアップを取得することができます。<br />
取得したバックアップやWALアーカイブはローカルストレージもしくはAmazon S3に保存することができ、保存先の設定はPostgreSQLクラスタ作成時に設定可能です。</p>
<p>バックアップに関するクラスタ作成時のオプションは以下のようなものがあります。</p>
<pre>$ pgo create cluster hippo \
--replica-count=1 \
<strong>--pgbackrest-storage-type="local,s3" \</strong>
<strong>--pgbackrest-s3-bucket="crunchy-postgres-backup" \</strong>
<strong>--pgbackrest-s3-region="us-west-2" \</strong>
<strong>--pgbackrest-s3-endpoint="s3.us-west-2.amazonaws.com" \</strong>
<strong>--pgbackrest-s3-key="xxxxxxxxxx" \</strong>
<strong>--pgbackrest-s3-key-secret="xxxxxxxxxxxxxxxxxxxx" \</strong>
<strong>--pgbackrest-s3-verify-tls=false</strong></pre>
<p>それぞれのオプションの意味は以下の通りです。</p>
<ul>
<li><strong><code>--pgbackrest-storage-type</code></strong>: バックアップとWALアーカイブの保存先。&#8221;local,s3&#8243;を指定した場合は、ローカルストレージとAmazon S3に保存します。デフォルトではローカルストレージに保存します。</li>
<li><strong><code>--pgbackrest-s3-bucket</code></strong>: Amazon S3のBucket名を指定します。</li>
<li><strong><code>--pgbackrest-s3-region</code></strong>: Amazon S3のリージョンを指定します。</li>
<li><strong><code>--pgbackrest-s3-endpoint</code></strong>: Amazon S3のエンドポイントを指定します。</li>
<li><strong><code>--pgbackrest-s3-key</code></strong>: Amazon S3 キーを指定します。</li>
<li><strong><code>--pgbackrest-s3-key-secret</code></strong>: Amazon S3 シークレットキーを指定します。</li>
<li><strong><code>--pgbackrest-s3-verify-tls</code></strong>: pgBackRestがAmazon S3に接続するときにTLS証明書を検証するかどうかを設定します。</li>
</ul>
<p>定期バックアップを設定するには<strong>pgo create schedule</strong>コマンドを使います。<br />
バックアップのスケジュールはcron表記で指定します。</p>
<pre>(毎日午前1時にフルバックアップを実行)
$ pgo create schedule hippo --schedule="0 1 * * *" \
--schedule-type=pgbackrest --pgbackrest-backup-type=full</pre>
<p>差分バックアップを行いたい場合は、<strong><code>--pgbackrest-backup-type=incr</code></strong>を指定します。</p>
<pre>(1時間ごとに差分バックアップを実行)
$ pgo create schedule hippo --schedule="0 */1 * * *" \
--schedule-type=pgbackrest --pgbackrest-backup-type=incr
</pre>
<h2>リストア</h2>
<h3>新しいPostgreSQLクラスタの作成</h3>
<p>バックアップから新しいPostgreSQLクラスタを作成するには<strong>pgo create cluster</strong>を利用します。<br />
例えば、開発やテスト目的で本番環境と同じ環境を用意するときに、<strong><code>--restore-from</code></strong>オプションを使用して本番環境の名前を指定するだけです。</p>
<pre>pgo create cluster hippo2 --restore-from=hippo</pre>
<p>デフォルトでは最新のデータに復元しますが、<strong><code>--restore-opts</code></strong>オプションを使用して、特定の時点まで復元可能です。</p>
<pre>pgo create cluster hippo2 \
--restore-from=hippo \
--restore-opts="--type=time --target='2020-07-27 14:50:00.000000+00'"</pre>
<p>また、Amazon S3に保存されているバックアップからPostgreSQLクラスタを作成する場合は、<br />
<strong><code>--repo-type=s3</code></strong>を指定します。</p>
<pre>pgo create cluster hippo2 --restore-from=hippo --restore-opts="--repo-type=s3"
</pre>
<h3>起動中のPostgreSQLクラスタのPITR</h3>
<p>起動中のPostgreSQLクラスタを以前の時点に復元するには<strong>pgo restore</strong>コマンドを使います。<br />
pgo restoreコマンドは既存のデータディレクトリでリカバリを実行しますので、<br />
クラスタが一旦停止され、作り直されます。</p>
<pre>$ pgo restore hippo --pitr-target="2020-07-27 14:50:00.000000+00" \
--backup-opts="--type=time"</pre>
<h2>ログ</h2>
<p>Crunchy PostgeSQL Operator自体にはログを収集する機能がありません。Podのsidecarコンテナとしてfluentdを導入し外部に転送するなどの作り込みは必要となります。</p>
<p>以下の方法でPodのログやPostgreSQLのログを確認可能です。<br />
クラスタの各Podのログは<strong>kubectl logs</strong>コマンドにより確認できます。</p>
<pre>kubectl logs hippo-646dfd49f5-x7m67 -c database -n pgo</pre>
<p>また、Pod内のPostgreSQLログは以下のように格納されています。</p>
<pre>kubectl exec -i -n pgo -t hippo-646dfd49f5-x7m67 -- ls -alt /pgdata/hippo/pg_log
-rw-------  1 postgres postgres  588 Jul  1 12:00 postgresql-Wed.log</pre>
<h2>アップグレード</h2>
<p>新しいバージョンにアップグレードするには、以下2段階のアップグレードを実行する必要があります。</p>
<ol>
<li>Crunchy Postgres Operator自身のアップグレード</li>
<li>PostgreSQLクラスタのアップグレード</li>
</ol>
<p>アップグレードに伴う注意点は以下の通りです。</p>
<ul>
<li>Operatorのアップグレード後、PostgreSQLクラスタのアップグレード完了まで既存のPostgreSQLクラスタの操作はできない。</li>
<li>PostgreSQLクラスタアップグレード時、replica及びreplicaのPVCが削除されるが、primaryとbackrest-repoのPVCがそのまま残り、それぞれの新しいPodに引き継がれる。</li>
<li>PostgreSQLクラスタのアップグレード中、primary Podが停止し、再作成されるので、PostgreSQLクラスタの<strong>ダウンタイム</strong>が発生する。</li>
</ul>
<h3>Crunchy Postgres Operatorのアップグレード</h3>
<p>前述の通り、pgo-deploy Jobにより、PostgreSQL Operatorをアップデートできるので、<br />
新しいバージョンのpostgres-operator.ymlにて<strong>DEPLOY_ACTION</strong>を<strong>update</strong>に変更し、適用します。</p>
<pre>$ vi postgres-operator.yml
...
- name: DEPLOY_ACTION
<strong>value: "install" -&gt; "update" に変更</strong>

$ kubectl apply -f postgres-operator.yml</pre>
<h3>PostgreSQLクラスタのアップグレード</h3>
<p>PostgreSQLクラスタのアップグレードには<strong>pgo upgrade</strong>コマンドを使います。</p>
<pre>$ pgo upgrade &lt;クラスタ名&gt;</pre>
<h2>便利な機能</h2>
<p>PostgreSQLクラスタ作成時に、オプションを指定することで、コネクションプールや<a href="http://pgbadger.darold.net/" target="_blank" rel="noopener noreferrer">pgbadger</a>によるPostgreSQLログ解析、<a href="https://prometheus.io/" target="_blank" rel="noopener noreferrer">Prometheus</a>監視用のメトリクスの出力といった機能が利用できます。</p>
<p>例えば、<strong>pgo create cluster</strong>でクラスタ作成時に<strong><code>--pgbouncer --metrics --pgbadger</code></strong>を指定することで、これら機能が有効になります。</p>
<pre>$ pgo create cluster hippo \ 
--replica-count=1 \ 
--pgbouncer \ 
--metrics \ 
--pgbadger</pre>
<p>それぞれのオプションの意味は以下の通りです。</p>
<ul>
<li><strong><code>--pgbouncer</code></strong>: pgbouncer Pod起動し、コネクションプール機能を有効にする</li>
<li><strong><code>--metrics</code></strong>: Prometheus Exporterコンテナを各それぞれのPostgreSQLのPodに追加し、データベースサーバのパフォーマンスや使用状況、PostgreSQLクラスタの状態などのPrometheusメトリクスを出力する</li>
<li><strong><code>--pgbadger</code></strong>: pgbadgerコンテナをそれぞれのPostgreSQLのPodに追加し、PostgreSQLのログを解析する</li>
</ul>
<h2>おわりに</h2>
<p>今回はPostgreSQL Operatorの1つCrunchy Postgres Operatorについて紹介しました。Crunchy Postgres Operatorを用いることで、Kubernetes上のPostgreSQL HAクラスタの構築・管理が非常に容易になります。開発元が新機能の追加や機能改善に力をいれており、PostgreSQLの最新バージョンに対応するスピードも速く、Kubernets上でPostgreSQLクラスタの構築を検討する際に、1<span class="st">つの有力な選択肢だ</span>と言えるでしょう。</p>
<p>&nbsp;</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/oss-pro-support/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-oss" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、各種OSS のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
