首次使用 Kubernetes(Minikube) Pod 进行协作和数据持久化
总结
继上次“在初次使用kubernetes(Minikube)的Windows环境进行教程+α之后”,我尝试了应用服务器Pod和数据库服务器Pod的协作,并以备忘录形式记录下我所理解的内容。
当执行minikube命令时,请以管理员权限执行。
执行环境
-
- Windows 10 pro
-
- Minikube v0.28.0
- Docker Version 18.06.1-ce-win73 (19507)
立即开始操作指南
获取示例应用程序
请使用一个简单的示例应用程序,从Node.js应用程序中获取Redis数据并进行显示,因此请将源代码克隆到本地。
为了方便在本地进行预先操作确认,我们还准备了docker-compose。请根据需要灵活使用。
const http = require('http');
const redis = require('redis');
let redis_host = 'redis';
let redis_port = 6379;
// k8s環境の場合は、redisの接続先とポートは環境変数から取得
if (process.env.MODE && process.env.MODE == 'k8s') {
redis_host = process.env.SAMPLE_REDIS_SERVICE_HOST;
redis_port = process.env.SAMPLE_REDIS_SERVICE_PORT;
}
const client = redis.createClient({
host: redis_host,
port: redis_port
});
// 表示用の変数をredisに保存する
client.set('sample', 'hello world');
client.set('sample2', 'hello Qiita');
// 表示用の変数
let redis_val = '';
client.get('sample', function (err, data) {
redis_val += '<li>' + data + '</li>';
});
client.get('sample2', function (err, data) {
redis_val += '<li>' + data + '</li>';
});
const handleRequest = function (request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('<h1>redis value:</h1><ul>' + redis_val + '</ul>');
};
// echo env
const envs = process.env;
console.log(envs);
const www = http.createServer(handleRequest);
www.listen(3000);
2. 更改Docker客户端的连接目标
请预先将Docker客户端的目标更改为Minikube,与上次一样。
> minikube docker-env --shell powershell | Invoke-Expression
> docker images
# kubernetes関連のイメージが表示されればOK
3. 形象构建
在Minikube上构建示例应用程序的Docker镜像。
> docker build -t sample-app:v1 --no-cache ./app
4. 部署
将其部署到Minikube上。
> kubectl apply -f ./deployment_k8s_sample_app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-redis
labels:
app: sample-redis
type: db
spec:
replicas: 1
selector:
matchLabels:
app: sample-redis
type: db
template:
metadata:
labels:
app: sample-redis
type: db
spec:
containers:
- name: sample-redis
image: redis:4
ports:
- containerPort: 6379
# redis-volumeボリュームとredisのデータ領域の/data
volumeMounts:
- mountPath: /data
name: redis-volume
# データ永続化するためのボリューム
volumes:
- name: redis-volume
# ボリュームの種別はhostPath
hostPath:
path: /home/docker/redis-data
# ディレクトリがなければ作る
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: sample-redis
labels:
app: sample-redis
type: db
spec:
type: LoadBalancer
selector:
app: sample-redis
type: db
ports:
- port: 6379
targetPort: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
labels:
app: sample-app
type: app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
type: app
template:
metadata:
labels:
app: sample-app
type: app
spec:
containers:
- name: sample-app
image: sample-app:v1
ports:
- containerPort: 3000
# k8s環境用で稼働しているかどうかの環境変数
env:
- name: MODE
value: k8s
---
apiVersion: v1
kind: Service
metadata:
name: sample-app
labels:
app: sample-app
type: app
spec:
type: LoadBalancer
selector:
app: sample-app
type: app
ports:
- port: 3000
确认
确认Pod
> kubectl get po
NAME READY STATUS RESTARTS AGE
sample-app-694d9bf49f-66b7b 1/1 Running 0 37m
sample-redis-55c5b46859-n7pnt 1/1 Running 0 42m
确认服务 (Confirmation of service)
> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
sample-app LoadBalancer 10.101.237.112 <pending> 3000:32482/TCP 43m
sample-redis LoadBalancer 10.111.4.116 <pending> 6379:32400/TCP 43m
确认应用程序
> minikube service sample-app
只要在浏览器中显示以下内容,就可以了。
redis value:
hello world
hello Qiita
解释
可以通过获取与Docker相同的DB Pod(redis)连接信息环境变量来实现。但是,必须将其作为服务公开。通过使用服务,可以实现流量负载均衡、服务发现以及在集群内使用DNS。因此,从环境变量中获取应用程序的redis连接目标。
服务器.js
// k8s環境の場合は、redisの接続先とポートは環境変数から取得
// MODEはDeploymentで環境変数として設定しています
if (process.env.MODE && process.env.MODE == 'k8s') {
redis_host = process.env.SAMPLE_REDIS_SERVICE_HOST;
redis_port = process.env.SAMPLE_REDIS_SERVICE_PORT;
}
我们来检查一下环境变量吧。
kubectl logs sample-app-694d9bf49f-66b7b
{ KUBERNETES_SERVICE_PORT: '443',
KUBERNETES_PORT: 'tcp://10.96.0.1:443',
SAMPLE_APP_PORT_3000_TCP_ADDR: '10.97.74.141',
NODE_VERSION: '6.9.2',
HOSTNAME: 'sample-app-565db6587d-xtblr',
MODE: 'k8s',
SAMPLE_APP_PORT_3000_TCP_PORT: '3000',
SAMPLE_APP_PORT_3000_TCP_PROTO: 'tcp',
HOME: '/root',
SAMPLE_REDIS_SERVICE_HOST: '10.103.205.192',
SAMPLE_APP_PORT_3000_TCP: 'tcp://10.97.74.141:3000',
SAMPLE_APP_SERVICE_HOST: '10.97.74.141',
SAMPLE_REDIS_PORT: 'tcp://10.103.205.192:6379',
SAMPLE_REDIS_SERVICE_PORT: '6379',
SAMPLE_REDIS_PORT_6379_TCP_ADDR: '10.103.205.192',
KUBERNETES_PORT_443_TCP_ADDR: '10.96.0.1',
PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
SAMPLE_REDIS_PORT_6379_TCP_PORT: '6379',
KUBERNETES_PORT_443_TCP_PORT: '443',
SAMPLE_REDIS_PORT_6379_TCP_PROTO: 'tcp',
SAMPLE_APP_PORT: 'tcp://10.97.74.141:3000',
SAMPLE_APP_SERVICE_PORT: '3000',
NPM_CONFIG_LOGLEVEL: 'info',
KUBERNETES_PORT_443_TCP_PROTO: 'tcp',
SAMPLE_REDIS_PORT_6379_TCP: 'tcp://10.103.205.192:6379',
KUBERNETES_PORT_443_TCP: 'tcp://10.96.0.1:443',
KUBERNETES_SERVICE_PORT_HTTPS: '443',
KUBERNETES_SERVICE_HOST: '10.96.0.1',
PWD: '/' }
数据的持久化
为了持久化数据,我们将卷定义为hostPath。hostPath可以将任何节点上的路径作为卷使用。如果只是一个单节点的Minikube环境,那么这没有问题,但是在多节点配置的情况下,我们必须考虑数据的一致性,因此需要使用其他类型的卷。
以下是数据持久化验证步骤的内容。
1. 部署、服务的删除
为了确认数据是否持久化,我们将先进行一次删除操作。
> kubectl delete -f ./deployment_k8s_sample_app.yml
修改server.js文件
我会将代码中保存值到Redis的部分注释掉。
// 表示用の変数をredisに保存する
// client.set('sample', 'hello world');
// client.set('sample2', 'hello Qiita');
3. 重塑形象
标签使用v2进行构建。
> docker build -t sample-app:v2 --no-cache ./app
编辑deployment_k8s_sample_app.yml文件。
将部署的图像更改为v2版本。
~中略~
containers:
- name: sample-app
image: sample-app:v2
~中略~
5. 部署再次完成
> kubectl apply -f ./deployment_k8s_sample_app.yml
deployment.apps "sample-redis" created
service "sample-redis" created
deployment.apps "sample-app" created
service "sample-app" created
动作验证
可以通过前述的方式确认数值
> minikube service sample-app