8

使用kubernetes搭建简单的应用

 3 years ago
source link: https://www.yangyanxing.com/article/simple-app-in-k8s.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近在看kubernetes的相关内空,参考《Kubernetes权威指南》第一章,搭建一个简单的应用,它里面使用的是RC,我直接使用RS来搭建。

我们通过kubernetes来部署一个应用,这个应用后台是一个php网站,数据库使用redis,redis采用一主两从的部署方式,做到读写分离,写操作走redis主库,读操作走reids从库。并且启动多个应用副本,达到负载均衡,总体的应用架构如下图

k8s2.jpg

创建redis-master 服务

老版本的kubernetes使用RC(ReplicationController)来创建pod,但是随着RS(ReplicationSet)的出现,已经取代了RC,所以我们直接采用RS来创建pod,创建redis-master.yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
matchLabels:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: r-master
image: kubeguide/redis-master
ports:
- containerPort: 6379

yaml文件的编写很是麻烦,尤其是apiVersion: apps/v1 的选择,不同的apiVersion 对应下面的指令不同,写好的yaml文件可以在 https://kubeyaml.com/ 这个网站上校验一下。

通过 kubectl create -f redis-master.yaml 命令创建ReplicaSet, 使用 kubectl get pod 来查看pod的创建情况

1
2
3
# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-master-n6wbp 0/1 ContainerCreating 0 11s

过一会就可以创建成功了,过程中通过status查看状态,有时会创建失败,失败的原因很多,遇到到在网上搜索一下吧。到时候再进行总结。

创建完pod以后,如果没有创建与之对应的service,则该pod也无法正常工作,接下来先创建这个service

apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
name: redis-master
spec:
ports:
- port: 6379
targetPort: 6379
selector:
name: redis-master

使用 kubectl create -f redis-master-service.yaml 创建service,使用kubectl get services 查看service状态。

1
2
3
4
5
6
# kubectl create -f redis-master-service.yaml 
service/redis-master created
# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
redis-master ClusterIP 10.109.162.197 <none> 6739/TCP 10s

看到redis-master使用了10.109.162.197 这个虚拟的ip,之后创建的pod可以使用这个ip和端口访问这个redis服务。

通过kubernetes创建的pod,虚拟IP是动态的,如果重启以后可能就会变了,所以其它的服务如redis-slave要同步的话是不能使用这个虚拟IP的,kubernetes通过环境变量来记录从服务到虚拟IP的关系。

创建redis-slave 服务

创建redis-slave.yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
replicas: 2 #创建两个副本
selector:
matchLabels:
name: redis-slave
template:
metadata:
labels:
name: redis-slave
spec:
containers:
- name: r-slave
image: kubeguide/guestbook-redis-slave
env: #添加环境变量
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 6379
1
2
3
4
5
6
7
# kubectl create -f redis-slave.yaml 
replicaset.apps/redis-slave created
# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-master-n6wbp 1/1 Running 0 37m
redis-slave-7zj5x 0/1 ContainerCreating 0 12s
redis-slave-hp2pt 0/1 ContainerCreating 0 12s

我们来查看一下redis-slave中的环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-master-n6wbp 1/1 Running 0 39m
redis-slave-7zj5x 1/1 Running 0 2m7s
redis-slave-hp2pt 1/1 Running 0 2m7s
root@kubernetes-master:/usr/local/docker/kubernetes/yaml/phpredis# kubectl exec redis-slave-7zj5x env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=redis-slave-7zj5x
GET_HOSTS_FROM=env
REDIS_MASTER_SERVICE_HOST=10.109.162.197
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT_6739_TCP=tcp://10.109.162.197:6739
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
REDIS_MASTER_PORT_6739_TCP_PORT=6739
REDIS_MASTER_PORT_6739_TCP_ADDR=10.109.162.197
KUBERNETES_SERVICE_PORT=443
REDIS_MASTER_PORT_6739_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
REDIS_MASTER_PORT=tcp://10.109.162.197:6739
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
REDIS_VERSION=3.0.3
REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.0.3.tar.gz
REDIS_DOWNLOAD_SHA1=0e2d7707327986ae652df717059354b358b83358
HOME=/root
1
2
REDIS_MASTER_SERVICE_HOST=10.109.162.197
REDIS_MASTER_SERVICE_PORT=6379

可以通过这两个环境变量来动态获取上面redis-master的IP与PORT

然后再创建与redis-slave对应的service服务

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
ports:
- port: 6379
targetPort: 6379
selector:
name: redis-slave

通过kubectl get service 看到现在已经有三个服务了。

1
2
3
4
5
# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
redis-master ClusterIP 10.109.162.197 <none> 6379/TCP 31m
redis-slave ClusterIP 10.104.211.17 <none> 6379/TCP 18s

创建PHP应用

yaml文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: phpserver
labels:
name: phpserver
spec:
replicas: 3
selector:
matchLabels:
name: phpserver
template:
metadata:
labels:
name: phpserver
spec:
containers:
- name: phpfront
image: kubeguide/guestbook-php-frontend
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 80

创建pod,并查看pod状态

1
2
3
4
5
6
7
8
9
10
# kubectl create -f phpfront.yaml 
replicaset.apps/phpserver created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
phpserver-5bwzh 0/1 ContainerCreating 0 7s
phpserver-6v4dd 0/1 ContainerCreating 0 7s
phpserver-dbdmn 0/1 ContainerCreating 0 7s
redis-master-n6wbp 1/1 Running 0 53m
redis-slave-7zj5x 1/1 Running 0 16m
redis-slave-hp2pt 1/1 Running 0 16m

创建相应的service

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: phpservice
labels:
name: phpservice
spec:
type: NodePort
ports:
- port: 80
nodePort: 30001
selector:
name: phpserver

运行创建命令并且查看services

1
2
3
4
5
6
7
8
# kubectl create -f phpservice.yaml 
service/phpservice created
# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
phpservice NodePort 10.100.94.114 <none> 80:30001/TCP 9s
redis-master ClusterIP 10.109.162.197 <none> 6739/TCP 45m
redis-slave ClusterIP 10.104.211.17 <none> 6739/TCP 14m

注意到phpservice的type为NodePort,ports为80:30001/TCP,则这时可以通过主机的30001端口来访问该应用

访问 http://192.168.206.128:30001/ 来访问应用

k8s3.jpg

动态调整资源

可以手工的调整pod资源数量,如网站今天要做活动,预料到流量会增加,需要增加一些副本,则可以使用

kubectl scale rs rsname --replicas=4 命令来改变副本的数量,–replicas 值为要修改的量,当活动结束以后再手工的改回来。

当然对于这种纯手工的来修改副本数,还是不够智能,我们真正希望的是,当一个网站流量变大的时候可以自动的扩容,当网站的流量减少的时候,可以自动的缩容。

这个可以通过 HPA 来实现

  1. 环境变量是怎么传递的

  2. spec.type的类型

    Kubernetes的三种外部访问方式


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK