3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

k8s環境ハンズオン webアプリケーション構築実践編

Posted at

k8s環境ハンズオン webアプリケーション構築実践編

本セクションではminikubeの中に三層アプリを構築してきます。

  • デバッグ用イメージ作成
  • DBサーバーのイメージ作成
  • DBサーバーの構築(ストレージ)
  • DBサーバーの構築(Pod)
  • DBサーバーの構築(Pod+Secret)
  • DBサーバーの構築(StatefulSet)
  • DBサーバーの構築(HeadlessService)
  • DBサーバーの構築(初期化)
  • APサーバーのイメージ作成
  • APサーバーの構築(Pod+Secret)
  • APサーバーの構築(Deployment)
  • APサーバーの構築(Service)
  • WEBサーバーのイメージ作成
  • WEBサーバーの構築(Pod)
  • WEBサーバーの構築(Pod+ConfigMap)
  • WEBサーバーの構築(Deployment)
  • WEBサーバーの構築(Service)
  • Webアプリケーションの公開(Ingress)

作成するアプリ

minikubeの中に三層アプリを構築

web→ap→db→localstorage


デバッグ用イメージ作成

実装

  1. 以下の3ファイルを作成
    mongodb-org-4.0.repo
    Dockerfile
    debug-pod.yml

確認
Docker
1. Dockerで作成したイメージを実行
2. 実行中コンテナに入る
3. 必要なコマンドが実行可能なことを確認

Kubernetes
1. Podを作成

mongodb-org-4.0.repo
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
FROM centos:7

COPY . /tmp/debug

RUN  \
# Install MongoDB shell, tools.
mv /tmp/debug/mongodb-org-4.0.repo /etc/yum.repos.d; \
yum install -y mongodb-org-shell-4.0.5 mongodb-org-tools-4.0.5; \
# Install ip , ifconfig command.
yum install -y iproute net-tools; \
# Install jq
curl -o /usr/local/bin/jq -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64; \
chmod +x /usr/local/bin/jq; \
# Delete cache files.
yum clean all;
debug-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: default
spec:
  containers:
    - name: debug
      image: debug
      imagePullPolicy: Never
      command:
        - "sh"
        - "-c"
      args:
        - |
          while true
          do
            sleep 5
          done

上記3ファイルをvmにうつし、ビルドコマンド実行
(dockerfileにビルド申請を投げかける)

docker build -t debug .

debugイメージの確認

docker image ls

debugイメージを実行する

docker run -it debug sh

入り込んだコンテナで下記のコマンドでipを確認

ip;mongo;ifconfig;

mongodbが正しく動いている確認したら
コンテナを削除する。

docker container prune

続いてk8sで動作させるマニフェストファイルapplyする

kubectl apply -f debug-pod.yml
# 動作確認
kubectl get pod

中に入って動作確認する

kubectl exec -it debug sh
ip;mongo;ifconfig;

exit;
# 動作確認
kubectl get pod

DBサーバーのイメージ作成

実装

  1. 以下の3ファイルを作成
    .dockerignore
    docker-entrypoint.sh
    Dockerfile

確認

  1. Dockerで作成したイメージを実行
  2. 実行中コンテナに入る
  3. MongoDBに接続できることを確認
.dockerignore
**/.git
**/.DS_Store
**/node_modules
# ! /bin/sh
INIT_FLAG_FILE=/data/db/init-completed
INIT_LOG_FILE=/data/db/init-mongod.log

start_mongod_as_daemon() {
echo 
echo "> start mongod ..."
echo 
mongod \
  --fork \
  --logpath ${INIT_LOG_FILE} \
  --quiet \
  --bind_ip 127.0.0.1 \
  --smallfiles;
}

create_user() {
echo
echo "> create user ..."
echo
if [ ! "$MONGO_INITDB_ROOT_USERNAME" ] || [ ! "$MONGO_INITDB_ROOT_PASSWORD" ]; then
  return
fi
mongo "${MONGO_INITDB_DATABASE}" <<-EOS
  db.createUser({
    user: "${MONGO_INITDB_ROOT_USERNAME}",
    pwd: "${MONGO_INITDB_ROOT_PASSWORD}",
    roles: [{ role: "root", db: "${MONGO_INITDB_DATABASE:-admin}"}]
  })
EOS
}

create_initialize_flag() {
echo
echo "> create initialize flag file ..."
echo
cat <<-EOF > "${INIT_FLAG_FILE}"
[$(date +%Y-%m-%dT%H:%M:%S.%3N)] Initialize scripts if finigshed.
EOF
}

stop_mongod() {
echo
echo "> stop mongod ..."
echo
mongod --shutdown
}

if [ ! -e ${INIT_LOG_FILE} ]; then
  echo 
  echo "--- Initialize MongoDB ---"
  echo 
  start_mongod_as_daemon
  create_user
  create_initialize_flag
  stop_mongod
fi

exec "$@"
FROM alpine:3.9

COPY docker-entrypoint.sh /usr/local/bin

RUN \
adduser -g mongodb -DH -u 1000 mongodb; \
apk --no-cache add mongodb=4.0.5-r0; \
chmod +x /usr/local/bin/docker-entrypoint.sh; \
mkdir -p /data/db; \
chown -R mongodb:mongodb /data/db;

VOLUME /data/db

EXPOSE 27017

ENTRYPOINT [ "docker-entrypoint.sh" ]
CMD [ "mongod" ]

セットしたdockerfileをビルドする。

docker build -t weblog-db:v1.0.0 .

dockerをデーモン起動する。

docker run -d weblog-db:v1.0.0

起動しているかコンテナ一覧確認

[root@localhost ~]# docker container ls
CONTAINER ID        IMAGE                           COMMAND                   CREATED              STATUS              PORTS               NAMES
46aa0fa9b017        2d3813851e87                    "kube-scheduler --bi…"    About a minute ago   Up About a minute                       k8s_kube-scheduler_kube-scheduler-minikube_kube-system_31d9ee8b7fb12e797dc981a8686f6b2b_6
88649a10f187        weblog-db:v1.0.0                "docker-entrypoint.s…"    3 minutes ago        Up 3 minutes        27017/tcp           gifted_spence

コンテナの中に入ってmongodbが動作しているか確認

docker exec -it gifted_spence sh

mongodbが正しく動いている確認

show dbs

dockerコンテナ停止して削除

[root@localhost ~]# docker stop gifted_spence
gifted_spence
[root@localhost ~]# docker system prune

DBサーバーの構築(ストレージ)

実装

  1. 以下のファイルを作成
    weblog-db-storage.yml

確認
※必要なフォルダが作成されていること

  1. PersistentVolume、PersistentVolumeClaimを作成
  2. 作成したリソースを確認
weblog-db-storage.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/storage"
    type: Directory

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: storage-claim
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

DBサーバーの構築(Pod)

実装

  1. 以下のファイルを作成
    weblog-db-pod.yml

確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること

  1. PersistentVolume, PersistentVolumeClaim, Podを作成
  2. MongoDBのファイルが作成されていることを確認
  3. 作成したPodへ入る
  4. MongoDBへ接続確認
weblog-db-pod.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/storage"
    type: Directory

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: storage-claim
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

---
apiVersion: v1
kind: Pod
metadata:
  name: mongodb
  namespace: default
  labels:
    app: weblog
    type: database
spec:
  containers:
  - name: mongodb
    image: weblog-db:v1.0.0
    imagePullPolicy: Never
    command:
    - "mongod"
    - "--bind_ip_all"
    volumeMounts:
    - mountPath: /data/db
      name: storage
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: storage-claim

DBサーバーの構築(Pod+Secret)

実装

  1. keyfile(ランダム文字列)を作成
  2. Secretリソースを作成
  3. SecretリソースのYAMLを取得
  4. weblog-db-pod.ymlへマージ
  5. Secretリソースを削除

確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること

  1. PersistentVolume, Pod, Secretを作成
  2. 作成したPodへ入る
  3. MongoDBへ接続
  4. 設定したユーザー名/パスワードで認証
  5. DB一覧を表示
DFCytNO0mwawyBs25EOwptvC1TicPzI39KkojjhfE7HeR/VvryeNwqdOvOwiZ9jP/pIWIeYUYiktZXfXhOOlyMBEwUCGr+umbmEeududNy4hQCsVe0YOSlX07Xqa//o+mz4Z8pEchN0wUahqpHD5ieFyoMNIVaEcFPF43+3vZovw7M4xaY+xhhnW5etgm/c2g9GaGlJ4aXPXJbHQTylscnivBrmWiIY+JAPc+oFGJL5I3OCiSR1d66gG99ysof76Rtx0MvYgWdX9rSe16odaI3IWtmhI2CLbWpS994nYcWTCbtor3fMC1cs8nNRWy1un+JbbPooMqiRObxRncHap2X+pOKtjYPg+YKX1Htf+XyaH7DrFdZMnsVbAtAgV6Cf67IZym65p8LjjFkhZTbn5ZMgjQinwerkB+QC5hmaQQhAu6z5te+kPrsQg4PQ/JCRL7vweZEzddwlCo8NYGUJXaSG0Lg2k7wDx9oHLTuA/Telit2VrfgRbU6Y6f6FEOczjKnHKgHT09RJa56wdihgHreyWbVCC7BfdFJ2zRj1fG5YEgpkA3pgMsuvUDi6Ai6tNVe3O3jAqCmXghpFbryi9XYgtDsQkpGPRUZyLvNBj5k8qBoiYkiHPWvyIbyB9SX0pcyP10R8zR0TB8pXUZb3Xh1p4VDMTtg5u8Wwf56pIrWe3KYj20P2wWyQ3glDo5GMJxUdoubTxOun2+V0J6Oc0dKlmweqEjAbakJiDdyvty2OggnbgRSNYZInNKVR9nbnPUE/kCSMbNeE5hVVFC0zx6FKHkdxiZFEv8bP/LR4hY49OEZa9vuPRBn2LqflucO7wm5OnD8mN3PY8LlpN6SWCUTGJ2qfwm36vjRKpHxnFH6IcyDVwmbPulCMEnfnL5rKJ/4bZGiE1SQobQGYD/Gbq1UFWok0FMfTFV1wetQfVv32SISJ6PUJM2iThBJWDPNVTmKf28Dlq2NaLFMd1ugKxAWP2fN9YOgw6ZuiiRB/6UbIM7Ms2FWfytGp2oYcy94XP
weblog-db-pod+secret.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/storage"
    type: Directory

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: storage-claim
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

---
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---
apiVersion: v1
kind: Pod
metadata:
  name: mongodb
  namespace: default
  labels:
    app: weblog
    type: database
spec:
  containers:
  - name: mongodb
    image: weblog-db:v1.0.0
    imagePullPolicy: Never
    args:
    - "mongod"
    - "--auth"
    - "--bind_ip_all"
    env:
    - name: "MONGO_INITDB_ROOT_USERNAME"
      valueFrom:
        secretKeyRef:
          name: mongo-secret
          key: root_username
    - name: "MONGO_INITDB_ROOT_PASSWORD"
      valueFrom:
        secretKeyRef:
          name: mongo-secret
          key: root_password
    - name: "MONGO_INITDB_DATABASE"
      value: "admin"
    volumeMounts:
    - mountPath: /data/db
      name: storage
    - mountPath: /home/mongodb
      name: secret
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: storage-claim
  - name: secret
    secret:
      secretName: mongo-secret
      items:
      - key: keyfile
        path: keyfile
        mode: 0700

DBサーバーの構築(StatefulSet)

実装

  1. 以下のファイルを作成
    weblog-db-statefulset.yml

確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること

  1. PersistentVolume, Secret, StatefulSetを作成
  2. 作成したPodへ入る
  3. MongoDBへ接続
  4. 設定したユーザー名/パスワードで認証
  5. DB一覧を表示
weblog-db-statefulset.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-0
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0000"
    type: Directory

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-1
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0001"
    type: Directory

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-2
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0002"
    type: Directory

---
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongo
  namespace: default
  labels:
    app: weblog
    type: database
spec:
  selector:
    matchLabels:
      app: weblog
      type: database
  serviceName: db-svc
  replicas: 3
  template:
    metadata:
      name: mongodb
      namespace: default
      labels:
        app: weblog
        type: database
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mongodb
        image: weblog-db:v1.0.0
        imagePullPolicy: Never
        args:
        - "mongod"
        - "--auth"
        - "--clusterAuthMode=keyFile"
        - "--keyFile=/home/mongodb/keyfile"
        - "--replSet=rs0"
        - "--bind_ip_all"
        env:
        - name: "MONGO_INITDB_ROOT_USERNAME"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: root_username
        - name: "MONGO_INITDB_ROOT_PASSWORD"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: root_password
        - name: "MONGO_INITDB_DATABASE"
          value: "admin"
        volumeMounts:
        - mountPath: /data/db
          name: storage
        - mountPath: /home/mongodb
          name: secret
      volumes:
      - name: secret
        secret:
          secretName: mongo-secret
          items:
          - key: keyfile
            path: keyfile
            mode: 0700
  volumeClaimTemplates:
  - metadata:
      name: storage
    spec:
      storageClassName: slow
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi

DBサーバーの構築(HeadlessService)

実装

  1. 以下のファイルを作成
    weblog-db-fullset.yml

確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること

  1. PersistentVolume, Secret, StatefulSet, Serviceを作成
  2. 作成したPodへ入る
  3. MongoDBを初期化
  4. レプリカセット構築できていることを確認
weblog-db-fullset.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-0
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0000"
    type: Directory

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-1
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0001"
    type: Directory

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: storage-volume-2
  namespace: default
  labels:
    app: weblog
    type: storage
spec:
  storageClassName: slow
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/data/pv0002"
    type: Directory

---
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---
apiVersion: v1
kind: Service
metadata:
  name: db-svc
  namespace: default
  labels:
    app: weblog
    type: database
spec:
  ports:
  - port: 27017
    targetPort: 27017
  clusterIP: None
  selector:
    app: weblog
    type: database

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongo
  namespace: default
  labels:
    app: weblog
    type: database
spec:
  selector:
    matchLabels:
      app: weblog
      type: database
  serviceName: db-svc
  replicas: 3
  template:
    metadata:
      name: mongodb
      namespace: default
      labels:
        app: weblog
        type: database
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mongodb
        image: weblog-db:v1.0.0
        imagePullPolicy: Never
        args:
        - "mongod"
        - "--auth"
        - "--clusterAuthMode=keyFile"
        - "--keyFile=/home/mongodb/keyfile"
        - "--replSet=rs0"
        - "--bind_ip_all"
        env:
        - name: "MONGO_INITDB_ROOT_USERNAME"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: root_username
        - name: "MONGO_INITDB_ROOT_PASSWORD"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: root_password
        - name: "MONGO_INITDB_DATABASE"
          value: "admin"
        volumeMounts:
        - mountPath: /data/db
          name: storage
        - mountPath: /home/mongodb
          name: secret
      volumes:
      - name: secret
        secret:
          secretName: mongo-secret
          items:
          - key: keyfile
            path: keyfile
            mode: 0700
  volumeClaimTemplates:
  - metadata:
      name: storage
    spec:
      storageClassName: slow
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi

DBサーバーの構築(初期化)

  1. デバッグ用Podを起動
  2. 初期化スクリプトをデバッグ用Podへコピー
  3. デバッグ用Podへ入る
  4. MongoDBへ接続してプライマリを確認して切断
  5. 初期化スクリプトを修正(必要であれば)
  6. 初期化スクリプトを実行
  7. いずれかのMongoDBに接続してデータが入ったことを確認
adduser.js
// use weblog
db.createUser({
  user: "user",
  pwd: "welcome",
  roles: [{
    role: "readWrite", db: "weblog"
  }]
})
drop.js
db.posts.drop();
db.users.drop();
db.privileges.drop();
init.sh
# Create user 
mongo mongodb://mongo-0.db-svc:27017/weblog -u admin -p Passw0rd --authenticationDatabase admin ./adduser.js

# Create collection & insert initial data
mongo mongodb://mongo-0.db-svc:27017/weblog -u admin -p Passw0rd --authenticationDatabase admin ./insert.js
insert.js
//
// posts table
//
db.posts.createIndex({ url: 1 }, { unique: true, background: true });
db.posts.insertMany([{
  url: "/2017/05/hello-nodejs.html",
  published: new Date(2017, 4, 2),
  updated: new Date(2017, 4, 2),
  title: "ようこそ Node.js の世界へ",
  content: "Node.js は おもしろい!",
  keywords: ["Node.js"],
  authors: ["Yuta Sato"]
}, {
  url: "/2017/06/nodejs-basic.html",
  published: new Date(2017, 5, 12),
  updated: new Date(2017, 5, 12),
  title: "Node.js の 基本",
  content: "ちょっと難しくなってきた!?",
  keywords: ["Node.js"],
  authors: ["Yuta Sato"]
}, {
  url: "/2017/07/advanced-nodejs.html",
  published: new Date(2017, 7, 8),
  updated: new Date(2017, 7, 8),
  title: "Node.js 応用",
  content: "Node.js で Excel ファイルが触れるなんて!!",
  keywords: ["Node.js"],
  authors: ["Yuta Sato"]
}]);

//
// users table
//
db.users.createIndex({ email: 1 }, { unique: true, background: true });
db.users.insertMany([{
  email: "yuta.sato@sample.com",
  name: "Yuta Sato",
  password: "77d1fb804f4e1e6059377122046c95de5e567cb9fd374639cb96e7f5cc07dba1", //"qwerty", // "77d1fb804f4e1e6059377122046c95de5e567cb9fd374639cb96e7f5cc07dba1"
  role: "owner"
}]);

//
// privileges table
//
db.privileges.createIndex({ role: 1 }, { unique: true, background: true });
db.privileges.insertMany([
  { role: "default", permissions: ["read"] },
  { role: "owner", permissions: ["readWrite"] }
]);

APサーバーのイメージ作成

実装

  1. 以下のファイルを作成

    ROOT

    │ .dockerignore
    │ docker-entrypoint.sh
    │ Dockerfile

    │ --- 以下は Node.js アプリ Application フォルダに配置---
    │ app.js
    │ package.json
    │ yarn.lock

    ├─ api
    ├─ config
    ├─ lib
    ├─ log
    ├─ public
    ├─ routes
    └─ views

確認
※DBサーバーが起動して初期化まで済んでいること

  1. MongoDBのプライマリを確認
  2. MongoDBに対するService, Endpointsを作成(kubectl apply)
  3. Dockerで作成したイメージを実行(docker run)
  4. 作成したNode.jsアプリケーションコンテナへ接続(curl)
  5. MongoDB接続用Service, Endpointsを削除(kubectl delete)

APサーバーの構築(Pod+Secret)

実装

  1. 以下のファイルを作成
    weblog-app-pod.yml

確認
※DBサーバーが起動して初期化まで済んでいること

  1. Secret, Podを作成(kubectl apply)
  2. デバッグPodを作成して入る(kubectl exec)
  3. APサーバーPodへ接続確認(curl)
weblog-app-pod.yml
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  weblog_username: dXNlcg==     # user
  weblog_password: d2VsY29tZQ== # welcome
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---
apiVersion: v1
kind: Pod
metadata:
  name: nodeapp
  namespace: default
  labels:
    app: weblog
    type: application
spec:
  containers:
  - name: node
    image: weblog-app:v1.0.0
    imagePullPolicy: Never
    ports:
    - containerPort: 3000
    env:
    - name: "MONGODB_USERNAME"
      valueFrom:
        secretKeyRef:
          name: mongo-secret
          key: weblog_username
    - name: "MONGODB_PASSWORD"
      valueFrom:
        secretKeyRef:
          name: mongo-secret
          key: weblog_password
    - name: "MONGODB_HOSTS"
      value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017,"
    - name: "MONGODB_DATABASE"
      value: "weblog"
    - name: "MONGODB_REPLICASET"
      value: "rs0"

APサーバーの構築(Deployment)

実装

  1. 以下のファイルを作成
    weblog-app-deployment.yml

確認
※DBサーバーが起動して初期化まで済んでいること

  1. Secret, Deploymentを作成(kubectl apply)
  2. デバッグPodを作成して入る(kubectl exec)
  3. APサーバーPodへ接続確認(curl)
weblog-app-deployment.yml
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  weblog_username: dXNlcg==     # user
  weblog_password: d2VsY29tZQ== # welcome
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  namespace: default
  labels:
    app: weblog
    type: application
spec:
  replicas: 3
  selector:
    matchLabels:
      app: weblog
      type: application
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  revisionHistoryLimit: 14
  template:
    metadata:
      name: nodeapp
      namespace: default
      labels:
        app: weblog
        type: application
    spec:
      containers:
      - name: node
        image: weblog-app:v1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 3000
        env:
        - name: "MONGODB_USERNAME"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: weblog_username
        - name: "MONGODB_PASSWORD"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: weblog_password
        - name: "MONGODB_HOSTS"
          value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017,"
        - name: "MONGODB_DATABASE"
          value: "weblog"
        - name: "MONGODB_REPLICASET"
          value: "rs0"

APサーバーの構築(Service)

実装

  1. 以下のファイルを作成
    weblog-app-fullset.yml

確認
※DBサーバーが起動して初期化まで済んでいること

  1. Secret, Deployment, Serviceを作成(kubectl apply)
  2. デバッグPodを作成して入る(kubectl exec)
  3. APサーバーへService経由で接続(curl)
  4. APサーバーのいずれかにログ出力されていることを確認
weblog-app-fullset.yml
apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
  namespace: default
  labels:
    app: weblog
    type: database
type: Opaque
data:
  root_username: YWRtaW4=
  root_password: UGFzc3cwcmQ=
  weblog_username: dXNlcg==     # user
  weblog_password: d2VsY29tZQ== # welcome
  keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo=

---
apiVersion: v1
kind: Service
metadata:
  name: app-svc
  namespace: default
  labels:
    app: weblog
    type: application
spec:
  ports:
  - port: 3000
    targetPort: 3000
  selector:
    app: weblog
    type: application

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  namespace: default
  labels:
    app: weblog
    type: application
spec:
  replicas: 3
  selector:
    matchLabels:
      app: weblog
      type: application
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  revisionHistoryLimit: 14
  template:
    metadata:
      name: nodeapp
      namespace: default
      labels:
        app: weblog
        type: application
    spec:
      containers:
      - name: node
        image: weblog-app:v1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 3000
        env:
        - name: "MONGODB_USERNAME"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: weblog_username
        - name: "MONGODB_PASSWORD"
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key: weblog_password
        - name: "MONGODB_HOSTS"
          value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017,"
        - name: "MONGODB_DATABASE"
          value: "weblog"
        - name: "MONGODB_REPLICASET"
          value: "rs0"

WEBサーバーのイメージ作成

実装

  1. 以下のファイルを作成
    ROOT
    docker-entrypoint.sh
    Dockerfile

※nginx.confは添付を利用

確認
※Kubernetes上でDBサーバーとAPサーバーが起動していること

  1. APサーバーへアクセスするServiceを作成
  2. Webサーバーコンテナ起動
  3. 外部からブラウザでアクセスして画面確認
nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;

    keepalive_timeout  65;

    server_tokens   off;

    proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d;
    proxy_temp_path  /var/cache/nginx/tmp;

    server {
        listen        80;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
            proxy_pass http://${APPLICATION_HOST}/;
        }

        location /public/ {
            proxy_pass http://${APPLICATION_HOST}/public/;
            proxy_ignore_headers Cache-Control Expires;
            proxy_buffering on;
            proxy_cache STATIC;
            proxy_cache_valid any 10d;
            add_header X-Nginx-Cache $upstream_cache_status;
        }
    }

    # include /etc/nginx/conf.d/*.conf;
}
docker-entrypoint.sh
# ! /bin/sh

envsubst '$$APPLICATION_HOST' \
  < /home/nginx/nginx.conf \
  > /etc/nginx/nginx.conf

exec "$@"
FROM nginx:1.17.2-alpine

COPY . /home/nginx

RUN cd /home/nginx; \
    mv docker-entrypoint.sh /usr/local/bin; \
    chmod +x /usr/local/bin/docker-entrypoint.sh;

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]



weblog-app-service.yml
apiVersion: v1
kind: Service
metadata:
  name: nodeapp
  namespace: default
  labels:
    env: study
spec:
  type: NodePort
  selector:
    app: weblog
    type: application
  ports:
  - port: 3000
    targetPort: 3000
    nodePort: 30000

WEBサーバーの構築(Pod)

実装

  1. 以下のファイルを作成
    weblog-web-pod.yml

確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること

  1. ConfigMap, Deployment, Serviceを作成(kubectl apply)
  2. 作成したWebサーバーPodのIPアドレスを確認(kubectl get)
  3. デバッグPodを作成して入る(kubectl exec)
  4. Webサーバーへ接続(curl)
  5. 接続したWebサーバーにアクセスログがあることを確認
weblog-web-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: weblog
    type: frontend
spec:
  containers:
  - name: nginx
    image: weblog-web:v1.0.0
    imagePullPolicy: Never
    ports:
    - containerPort: 80
    env:
    - name: "APPLICATION_HOST"
      value: "app-svc:3000"

WEBサーバーの構築(Pod+ConfigMap)

実装

  1. 以下のファイルを作成
    weblog-web-pod+configmap.yml

確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること

  1. ConfigMap, Podを作成(kubectl apply)
  2. WebサーバーPodに入ってConfigMapを利用していることを確認(kubectl exec)
  3. WebサーバーPodのIPアドレスを確認(kubectl get)
  4. デバッグPodを作成して入る(kubectl exec)
  5. WebサーバーPodへ接続確認(curl)
weblog-web-pod+configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
  labels:
    app: weblog
    type: frontend
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;

        keepalive_timeout  65;

        server_tokens   off;

        proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d;
        proxy_temp_path  /var/cache/nginx/tmp;

        server {
            listen        80;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            location / {
                proxy_pass http://${APPLICATION_HOST}/;
            }

            location /public/ {
                proxy_pass http://${APPLICATION_HOST}/public/;
                proxy_ignore_headers Cache-Control Expires;
                proxy_buffering on;
                proxy_cache STATIC;
                proxy_cache_valid any 10d;
                add_header X-Nginx-Cache $upstream_cache_status;
            }
        }

        # include /etc/nginx/conf.d/*.conf;
        # ConfigMap
    }

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: weblog
    type: frontend
spec:
  containers:
  - name: nginx
    image: weblog-web:v1.0.0
    imagePullPolicy: Never
    ports:
    - containerPort: 80
    env:
    - name: "APPLICATION_HOST"
      value: "app-svc:3000"
    volumeMounts:
    - name: config-volume
      mountPath: /home/nginx
  volumes:
  - name: config-volume
    configMap:
      name: nginx-config

WEBサーバーの構築(Deployment)

実装

  1. 以下のファイルを作成
    weblog-web-deployment.yml

確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること

  1. ConfigMap, Deploymentを作成(kubectl apply)
  2. WebサーバーPodのIPアドレスを確認(kubectl get)
  3. デバッグPodを作成して入る(kubectl exec)
  4. WebサーバーPodいずれかへ接続確認(curl)
weblog-web-deployment.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
  labels:
    app: weblog
    type: frontend
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;

        keepalive_timeout  65;

        server_tokens   off;

        proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d;
        proxy_temp_path  /var/cache/nginx/tmp;

        server {
            listen        80;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            location / {
                proxy_pass http://${APPLICATION_HOST}/;
            }

            location /public/ {
                proxy_pass http://${APPLICATION_HOST}/public/;
                proxy_ignore_headers Cache-Control Expires;
                proxy_buffering on;
                proxy_cache STATIC;
                proxy_cache_valid any 10d;
                add_header X-Nginx-Cache $upstream_cache_status;
            }
        }

        # include /etc/nginx/conf.d/*.conf;
        # ConfigMap
    }

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: weblog
    type: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: weblog
      type: frontend
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  revisionHistoryLimit: 14
  template:
    metadata:
      name: nginx
      namespace: default
      labels:
        app: weblog
        type: frontend
    spec:
      containers:
      - name: nginx
        image: weblog-web:v1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 80
        env:
        - name: "APPLICATION_HOST"
          value: "app-svc:3000"
        volumeMounts:
        - name: config-volume
          mountPath: /home/nginx
      volumes:
      - name: config-volume
        configMap:
          name: nginx-config

WEBサーバーの構築(Service)

実装

  1. 以下のファイルを作成
    weblog-web-fullset.yml

確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること

  1. ConfigMap, Deploymentを作成(kubectl apply)
  2. デバッグPodを作成して入る(kubectl exec)
  3. WebサーバーServiceへ接続確認(curl)
weblog-web-fullset.yml
apiVersion: v1
kind: Service
metadata:
  name: web-svc
  namespace: default
  labels:
    app: weblog
    type: frontend
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: weblog
    type: frontend

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
  labels:
    app: weblog
    type: frontend
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;

        keepalive_timeout  65;

        server_tokens   off;

        proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d;
        proxy_temp_path  /var/cache/nginx/tmp;

        server {
            listen        80;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            location / {
                proxy_pass http://${APPLICATION_HOST}/;
            }

            location /public/ {
                proxy_pass http://${APPLICATION_HOST}/public/;
                proxy_ignore_headers Cache-Control Expires;
                proxy_buffering on;
                proxy_cache STATIC;
                proxy_cache_valid any 10d;
                add_header X-Nginx-Cache $upstream_cache_status;
            }
        }

        # include /etc/nginx/conf.d/*.conf;
        # ConfigMap
    }

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: weblog
    type: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: weblog
      type: frontend
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  revisionHistoryLimit: 14
  template:
    metadata:
      name: nginx
      namespace: default
      labels:
        app: weblog
        type: frontend
    spec:
      containers:
      - name: nginx
        image: weblog-web:v1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 80
        env:
        - name: "APPLICATION_HOST"
          value: "app-svc:3000"
        volumeMounts:
        - name: config-volume
          mountPath: /home/nginx
      volumes:
      - name: config-volume
        configMap:
          name: nginx-config

Webアプリケーションの公開(Ingress)

実装

  1. 以下のファイルを作成
    weblog-ingress.yml

確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
※Webサーバーが起動していること

  1. Ingressを作成(kubectl apply)
  2. minikubeへ接続確認(ブラウザ)
weblog-ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: entrypoint
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
  labels:
    app: weblog
    type: entrypoint
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: web-svc
          servicePort: 80
3
4
0

Register as a new user and use Qiita more conveniently

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?