🐥
Minikubeでk8sのwebアプリケーション公開を行う
Minikubeをインストール
brew install minikube
Minikubeを開始
minikube start --cpus 2 --memory 1800
kubectlのインストール
brew install kubernetes-cli
デバッグ用イメージ作成
Dockerfile
FROM centos:7
RUN \
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;
マニフェスト
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
コンテナ立ち上げ
docker build -t debug .
kubanates立ち上げ
kubectl apply -f debug.yml
DBコンテナ構築(MongoDB)
Dockerfile作成
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" ]
MongoDB初期化 shell script
#! /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
}
# 下記で初期化されていなければMongoDBを初期化する
# DBは最初の1回目は初期化しないとステートレスなものなのでつかえないため
if [ ! -e ${INIT_FLAG_FILE} ]; then
echo
echo "--- Initialize MongoDB ---"
echo
start_mongod_as_daemon
create_user
create_initialize_flag
stop_mongod
fi
exec "$@"
下記コマンドでbuildする
docker build -t weblog-db:v1.0.0 .
コンテナデーモン起動する
docker run weblog-db:v1.0.0 -d
起動確認
docker container ls
接続して起動確認
docker exec -it strange_euler sh
mongo
DBサーバー ストレージ作成
db.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 <= Dockerfileで指定したvolumeの位置を指定
name: storage
volumes:
- name: storage
persistentVolumeClaim:
claimName: storage-claim
作成
kubectl apply -f db.yml
DBサーバー シークレット情報登録
手順
- key作成
- secretリソース作成
- secretリソースのYMAL作成
- dbのpodに設定
- secretリソースの削除
1, key作成
openssl rand -base64 1024 | tr -d '\r\n' | cut -c 1-1024 > keyfile
opensslで乱数を生成し、trコマンドで改行を削除, cutで1024文字取得
2, secretリソース作成
root_userとroot_password, keyfileを作成
kubectl create secret generic mongo-secret \
--from-literal=root_user=admin \
--from-literal=root_password=Password \
--from-file=./keyfile
- secretリソースのYMAL作成
kubectl get secret/mongo-secret -o yaml
secretリソースをyaml形式で表示される
3, dbのpodに設定
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
--- <= ここを追加 secretのyamlで表示されたものを少し編集して記載する
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 <= secret名
key: root_username <= secretのキー名
- name: "MONGO_INITDB_ROOT_PASSWORD"
valueFrom:
secretKeyRef:
name: mongo-secret
key: root_password <= secretのキー名
- name: "MONGO_INITDB_DATABASE"
value: "admin"
volumeMounts:
- mountPath: /data/db
name: storage
- mountPath: /home/mongodb <= secretのkeyのマウント先
name: secret
volumes:
- name: storage
persistentVolumeClaim:
claimName: storage-claim
- name: secret <= keyfileをsecretからマウントする
secret: <= secretからデータを取得
secretName: mongo-secret
items:
- key: keyfile <= secretのキー名
path: keyfile <= secret作成時のファイルの位置
mode: 0700 <= アクセス権限
4, dbのpod作成
kubectl apply -f db.yml
statefullset作成
DBをレプリケーション化させる
1, PersistentVolume, secret, StatefullSet作成
2, Pod作成
statefullSetでたちあげるとコンテナの名前-連番となる
1, PersistentVolume, secret, StatefullSet作成
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: DirectoryOrCreate
---
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: DirectoryOrCreate
---
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: DirectoryOrCreate
---
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 <= 元々Podだった部分をStatefullSetにしてPodの起動数を3台にして1台がプライマリー、残りがセカンダリー(reader)にする
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
2, Pod作成
kubectl apply -f db.yml
Headlessサービスを立ち上げレプリカの設定を行う
Headlessサービス追加
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 <= Headlessサービスの立ち上げs
metadata:
name: db-svc
namespace: default
labels:
app: weblog
type: database
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None <= Noneを指定することでHeadlessサービスとして立ち上げることができる
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
適用
kubectl apply -f db.yml
一つのコンテナに入る
kubectl exec -it mongo-0 sh
他のコンテナにアクセスする
ping コンテナ名.Headlessサービス名
ping mongo-1.db-svc
appサーバー構築
まずdbを外部公開するserviceとendpoint作成
apiVersion: v1
kind: Service
metadata:
name: mongodb
namespace: default
labels:
env: study
spec:
ports:
- port: 27017
targetPort: 27017
nodePort: 32717 <= 外部公開するポート 30000~32767まで指定可能
type: NodePort <= 外部公開を行うのでNodePort
---
apiVersion: v1
kind: Endpoints <= サービスに接続するendpoint作成
metadata:
name: mongodb
namespace: default
labels:
env: study
subsets:
- addresses:
- ip: 172.17.0.11
ports:
- port: 27017
appのマニュフェスト作成
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
namespace: default
labels:
app: weblog
type: database
type: Opaque <= genericで一般的なsecret作成
data:
root_username: YWRtaW4=
root_password: UGFzc3cwcmQ=
weblog_username: dXNlcg== # user ローカルでbase64ハッシュした値を入力
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: <= secretからデータ取得
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"
appサーバーdevelopment作成
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 <= podをdevelopment化していく
metadata:
name: nodeapp
namespace: default
labels:
app: weblog
type: application
spec:
replicas: 3
selector:
matchLabels:
app: weblog
type: application
strategy:
rollingUpdate:
maxSurge: 1 <= ローリングアップデートの際に超過しても良いPod数
maxUnavailable: 1 <= ローリングアップデート時に同時に削除するPod数
type: RollingUpdate
revisionHistoryLimit: 14
template: <= 起動する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"
appサービス作成
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サーバー構築
コンテナ作成
Dockerfile
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;"]
docker-entrypoint.sh
#! /bin/sh
envsubst '$$APPLICATION_HOST' \
< /home/nginx/nginx.conf \
> /etc/nginx/nginx.conf
exec "$@"
マニフェスト
apiVersion: v1
kind: Service
metadata:
name: nodeapp
namespace: default
labels:
env: study
spec:
type: NodePort <= 外部公開したいので
selector: <= 接続したいpodを指定
app: weblog
type: application
ports:
- port: 3000
targetPort: 3000
nodePort: 30000
webサーバーPod作成
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 <= マウントするコンテナ側のpathを指定
volumes:
- name: config-volume
configMap:
name: nginx-config <= VolumeMountsと名前を一致させる必要がある
PodをDeployment化する
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
service作成
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: default
labels:
app: weblog
type: frontend
spec:
ports:
- port: 80
targetPort: 80
selector: <= deploymentのpod情報と一致させる必要がある
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-configs
外部公開用Ingress作成
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: entrypoint
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx" <= ingressにはいくつかのタイプがあるが今回はnginxを選択
nginx.ingress.kubernetes.io/ssl-redirect: "false" <= httpでアクセスするとhttpsにリダイレクトがかかるがその挙動を無効にする
labels:
app: weblog
type: entrypoint
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: web-svc <= 処理を流したいサービス名を指定する
servicePort: 80
Discussion