📌

Kubernetesで色々してみる

2022/01/05に公開約16,100字

個人用のメモみたいなものです。

nginxを公開してみる

nginx
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 8081
      targetPort: nginx-port

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 80
              name: nginx-port
              protocol: TCP


Go/MySQLの自作APIを公開してみる

データの永続化なしバージョン

mysql.yml
apiVersion: v1
kind: Service
metadata:
  name: mysql-server
spec:
  type: ClusterIP
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306
      protocol: TCP
  selector:
    app: mysql-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-server
spec:
  selector:
    matchLabels:
      app: mysql-server
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql-server
    spec:
      containers:
        - image: mysql@sha256:92ad1d7e3f8eb7e67d35bf251912fb7cd12676a601dc90b6beb1aece7c1f5073
          name: mysql
          resources:
          env:
            - name: MYSQL_USER
              value: go_user
            - name: MYSQL_PASSWORD
              value: password
            - name: MYSQL_ROOT_PASSWORD
              value: root
            - name: TZ
              value: Asia/Tokyo
            - name: MYSQL_DATABASE
              value: go_database
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-server-initdb
              mountPath: /docker-entrypoint-initdb.d
            - name: mysql-server-conf
              mountPath: /etc/mysql/conf.d
      volumes:
        - name: mysql-server-initdb
          configMap:
            name: mysql-server-initdb-config
        - name: mysql-server-conf
          configMap:
            name: mysql-server-conf-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-initdb-config
data:
  createdb.sql: |
    CREATE TABLE IF NOT EXISTS
    go_database.users(
        id serial,
        sex int NOT NULL,
        introduction VARCHAR(255) NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS
    go_database.posts(
        id serial,
        title VARCHAR(255) NOT NULL,
        content VARCHAR(255) NOT NULL,
        publish_date int NOT NULL,
        thumbnail_url VARCHAR(255),
        user_id bigint UNSIGNED NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(id),
        FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON UPDATE CASCADE
        ON DELETE CASCADE
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-conf-config
data:
  custom.cnf: |
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_bin

    default-time-zone = SYSTEM
    log_timestamps = SYSTEM

    [mysql]
    default-character-set = utf8mb4

    [client]
    default-character-set = utf8mb4

goapi.yml
apiVersion: v1
kind: Service
metadata:
  name: goapi
spec:
  type: NodePort
  selector:
    app: goapi
  ports:
    - port: 8080
      targetPort: goapi-port
      nodePort: 30090

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goapi
  labels:
    app: goapi
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goapi
  template:
    metadata:
      labels:
        app: goapi
    spec:
      containers:
        - name: goapi
          image: wakabaseisei/goapi:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 8080
              name: goapi-port
              protocol: TCP

下記コマンドで、デプロイする

$ kubectl apply -f ./k8s/mysql.yml --record
$ kubectl apply -f ./k8s/goapi.yml --record   

Podが起動しているかを確認

$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
goapi-5749446fd4-bckn9         1/1     Running   0          18h
mysql-server-8cd85fb7c-mtxth   1/1     Running   0          18h

NodePortで公開したポートにアクセスする

ホストにマウントして永続化するバージョン

mysql-pv.yml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
mysql.yml
apiVersion: v1
kind: Service
metadata:
  name: mysql-server
spec:
  type: ClusterIP
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306
      protocol: TCP
  selector:
    app: mysql-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-server
spec:
  selector:
    matchLabels:
      app: mysql-server
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql-server
    spec:
      containers:
        - image: mysql@sha256:92ad1d7e3f8eb7e67d35bf251912fb7cd12676a601dc90b6beb1aece7c1f5073
          name: mysql
          resources:
          env:
            - name: MYSQL_USER
              value: go_user
            - name: MYSQL_PASSWORD
              value: password
            - name: MYSQL_ROOT_PASSWORD
              value: root
            - name: TZ
              value: Asia/Tokyo
            - name: MYSQL_DATABASE
              value: go_database
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-server-initdb
              mountPath: /docker-entrypoint-initdb.d
            - name: mysql-server-conf
              mountPath: /etc/mysql/conf.d
            - name: mysql-server-data
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-server-initdb
          configMap:
            name: mysql-server-initdb-config
        - name: mysql-server-conf
          configMap:
            name: mysql-server-conf-config
        - name: mysql-server-data
          persistentVolumeClaim:
            claimName: mysql-pv-claim
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-initdb-config
data:
  createdb.sql: |
    CREATE TABLE IF NOT EXISTS
    go_database.users(
        id serial,
        sex int NOT NULL,
        introduction VARCHAR(255) NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS
    go_database.posts(
        id serial,
        title VARCHAR(255) NOT NULL,
        content VARCHAR(255) NOT NULL,
        publish_date int NOT NULL,
        thumbnail_url VARCHAR(255),
        user_id bigint UNSIGNED NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(id),
        FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON UPDATE CASCADE
        ON DELETE CASCADE
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-conf-config
data:
  custom.cnf: |
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_bin

    default-time-zone = SYSTEM
    log_timestamps = SYSTEM

    [mysql]
    default-character-set = utf8mb4

    [client]
    default-character-set = utf8mb4
goapi.yml
apiVersion: v1
kind: Service
metadata:
  name: goapi
spec:
  type: NodePort
  selector:
    app: goapi
  ports:
    - port: 8080
      targetPort: goapi-port
      nodePort: 30090
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goapi
  labels:
    app: goapi
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goapi
  template:
    metadata:
      labels:
        app: goapi
    spec:
      containers:
        - name: goapi
          image: wakabaseisei/goapi:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 8080
              name: goapi-port
              protocol: TCP

デプロイのお時間です

$ kubectl apply -f ./k8s/mysql-pv.yml --record
$ kubectl apply -f ./k8s/mysql.yml --record
$ kubectl apply -f ./k8s/goapi.yml --record   

PVとPVCの生存確認

$ kubectl get pv 
NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     
mysql-pv-volume   20Gi       RWO            Retain           Bound   
CLAIM                    STORAGECLASS            AGE
default/mysql-pv-claim   manual                  15h

$ kubectl get pvc
NAME             STATUS   VOLUME            CAPACITY   ACCESS MODES   
mysql-pv-claim   Bound    mysql-pv-volume   20Gi       RWO           
STORAGECLASS   AGE
manual         15h

Podを消してもデータが永続化されるか検証してみる

検証用のデータを登録する

$ kubectl exec -it $(kubectl get pod | grep mysql | cut -d " " -f 1) -c mysql -- mysql --user=go_user --password=password
mysql> desc users;
+--------------+---------------------+------+-----+-------------------+-----------------------------+
| Field        | Type                | Null | Key | Default           | Extra                       |
+--------------+---------------------+------+-----+-------------------+-----------------------------+
| id           | bigint(20) unsigned | NO   | PRI | NULL              | auto_increment              |
| sex          | int(11)             | NO   |     | NULL              |                             |
| introduction | varchar(255)        | NO   |     | NULL              |                             |
| created_at   | timestamp           | NO   |     | CURRENT_TIMESTAMP |                             |
| updated_at   | timestamp           | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+--------------+---------------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.01 sec)

mysql> desc posts;
+---------------+---------------------+------+-----+-------------------+-----------------------------+
| Field         | Type                | Null | Key | Default           | Extra                       |
+---------------+---------------------+------+-----+-------------------+-----------------------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL              | auto_increment              |
| title         | varchar(255)        | NO   |     | NULL              |                             |
| content       | varchar(255)        | NO   |     | NULL              |                             |
| publish_date  | int(11)             | NO   |     | NULL              |                             |
| thumbnail_url | varchar(255)        | YES  |     | NULL              |                             |
| user_id       | bigint(20) unsigned | NO   | MUL | NULL              |                             |
| created_at    | timestamp           | NO   |     | CURRENT_TIMESTAMP |                             |
| updated_at    | timestamp           | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+---------------+---------------------+------+-----+-------------------+-----------------------------+
8 rows in set (0.00 sec)

mysql> insert into users(sex, introduction) values (1, "It is so cool!");
Query OK, 1 row affected (0.01 sec)
mysql> insert into users(sex, introduction) values (1, "permanent");
Query OK, 1 row affected (0.01 sec)
mysql> insert into users(sex, introduction) values (2, "I am a woman");
Query OK, 1 row affected (0.00 sec)
mysql> insert into users(sex, introduction) values (1, "I am a man");
Query OK, 1 row affected (0.00 sec)
mysql> select * from users;
+----+-----+----------------+---------------------+---------------------+
| id | sex | introduction   | created_at          | updated_at          |
+----+-----+----------------+---------------------+---------------------+
|  1 |   1 | It is so cool! | 2022-01-07 17:23:54 | 2022-01-07 17:23:54 |
|  2 |   1 | permanent      | 2022-01-08 11:25:57 | 2022-01-08 11:25:57 |
|  3 |   2 | I am a woman   | 2022-01-08 11:26:23 | 2022-01-08 11:26:23 |
|  4 |   1 | I am a man     | 2022-01-08 11:26:43 | 2022-01-08 11:26:43 |
+----+-----+----------------+---------------------+---------------------+
4 rows in set (0.00 sec)

mysql> insert into posts(title, content, publish_date, user_id) values ("neew title", "I am a pianist", 11111111, 2);
Query OK, 1 row affected (0.00 sec)

mysql> select * from posts;
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
| id | title      | content        | publish_date | thumbnail_url | user_id | created_at          | updated_at          |
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
|  1 | neew title | I am a pianist |     11111111 | NULL          |       2 | 2022-01-08 11:29:05 | 2022-01-08 11:29:05 |
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
1 row in set (0.00 sec)
mysql> exit
Bye

PodのNameを確認する

$ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
goapi-5749446fd4-78574          1/1     Running   0          151m
mysql-server-747f8c9f6c-tw8j2   1/1     Running   0          141m

「mysql-server-747f8c9f6c-tw8j2」をdeleteしてみる

$  kubectl delete pod mysql-server-747f8c9f6c-tw8j2
pod "mysql-server-747f8c9f6c-tw8j2" deleted

再度、Podを確認

$ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
goapi-5749446fd4-78574          1/1     Running   0          152m
mysql-server-747f8c9f6c-7lspg   1/1     Running   0          35s

「mysql-server-747f8c9f6c-7lspg」という名前で再度配置された!

ではでは、データの永続化はされているのか......

$ kubectl exec -it $(kubectl get pod | grep mysql | cut -d " " -f 1) -c mysql -- mysql --user=go_user --password=password
mysql> select * from users;
+----+-----+----------------+---------------------+---------------------+
| id | sex | introduction   | created_at          | updated_at          |
+----+-----+----------------+---------------------+---------------------+
|  1 |   1 | It is so cool! | 2022-01-07 17:23:54 | 2022-01-07 17:23:54 |
|  2 |   1 | permanent      | 2022-01-08 11:25:57 | 2022-01-08 11:25:57 |
|  3 |   2 | I am a woman   | 2022-01-08 11:26:23 | 2022-01-08 11:26:23 |
|  4 |   1 | I am a man     | 2022-01-08 11:26:43 | 2022-01-08 11:26:43 |
+----+-----+----------------+---------------------+---------------------+
4 rows in set (0.01 sec)

mysql> select * from posts;
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
| id | title      | content        | publish_date | thumbnail_url | user_id | created_at          | updated_at          |
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
|  1 | neew title | I am a pianist |     11111111 | NULL          |       2 | 2022-01-08 11:29:05 | 2022-01-08 11:29:05 |
+----+------------+----------------+--------------+---------------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

Pod削除前のデータがきちんと永続化されていた!

MasterとSlave構成のMySQLを扱うバージョンは、別記事でまとめようと思う。

Discussion

ログインするとコメントできます