如何使用kubernetes撘建一个 前台是php + 后台是 redis 程序, 前台通过replacationController来控制有3个pod来做负载均衡, 后台有 一个master redis ,和2个slave redis来完成一个简单的小程序
(程序来源Kubernetes 权威指南)
k8s的安装:
(1)关闭防火墙
1 2 3 |
systemctl disable firewalld systemctl stop firewalld |
(2)安装etcd和Kubernets
1 |
yum install -y etcd kubernetes |
(3)修改配置文件,在/etc/sysconfig/docker 中照到 OPTIONS,追加如下内容:
1 |
--insecure-registry gcr.io |
追加完成之后的内容如下:
1 |
OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry gcr.io' |
然后修改文件/etc/kubernetes/apiserver 将 –admission_control 参数中的 ServiceAccount删除(如果不删除,会导致pod无法正常启动)
(4)启动相关服务
1 2 3 4 5 6 7 |
systemctl start etcd systemctl start docker systemctl start kube-apiserver systemctl start kube-controller-manager systemctl start kube-scheduler systemctl start kubelet systemctl start kube-proxy |
程序的部署
创建redis-master
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
apiVersion: v1 kind: ReplicationController metadata: name: redis-master labels: name: redis-master spec: replicas: 1 selector: name: redis-master template: metadata: labels: name: redis-master spec: containers: - name: master image: docker.io/kubeguide/redis-master ports: - containerPort: 6379 |
然后执行:
1 |
kubectl create -f redis-master-controller.yaml |
创建redis-master 服务:
1 2 3 4 5 6 7 8 9 10 11 12 |
apiVersion: v1 kind: Service metadata: name: redis-master labels: name: redis-master spec: ports: - port: 6379 targetPort: 6379 selector: name: redis-master |
然后执行:
1 |
kubectl create -f redis-master-service.yaml |
创建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 |
apiVersion: v1 kind: ReplicationController metadata: name: redis-slave labels: name: redis-slave spec: replicas: 2 selector: name: redis-slave template: metadata: labels: name: redis-slave spec: containers: - name: slave image: kubeguide/guestbook-redis-slave env: - name: GET_HOSTS_FROM value: env ports: - containerPort: 6379 |
执行:
1 |
kubectl create -f redis-slave-controller.yaml |
创建slave 的服务:
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: Service metadata: name: redis-slave labels: name: redis-slave spec: ports: - port: 6379 selector: name: redis-slave |
执行:
1 |
kubectl create -f redis-slave-service.yaml |
创建前台的frontend
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
apiVersion: v1 kind: ReplicationController metadata: name: frontend labels: name: frontend spec: replicas: 3 selector: name: frontend template: metadata: labels: name: frontend spec: containers: - name: frontend image: kubeguide/guestbook-php-frontend env: - name: GET_HOSTS_FROM value: env ports: - containerPort: 80 |
执行:
1 |
kubectl create -f frontend-controller.yaml |
创建服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: v1 kind: Service metadata: name: frontend labels: name: frontend spec: type: NodePort ports: - port: 80 nodePort: 30001 selector: name: frontend |
执行:
1 |
kubectl create -f frontend-service.yaml |
到这个地方,我们就完整的创建了一个实例,我第一次实验的时候因为写错了端口(6379,写成了6397结果怎么也没写入成功)
(需要注意的一个地方就是我们需要iptable的支持,因为pod之间数据的交互都是走iptables的)
好,那我们来一下这个实例都做了什么…..
1 2 3 4 5 6 |
kubectl get service NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend 10.254.58.3 nodes 80/TCP 5m kubernetes 10.254.0.1 <none> 443/TCP 4h redis-master 10.254.43.174 <none> 6379/TCP 8m redis-slave 10.254.3.44 <none> 6379/TCP 6m |
首先我们可以看到有3个服务(kubernetes那个我们就不算了),为什么需要服务呢?直接用IP不行么?
不行,因为我们的pod是持续变化的,一个pod挂了,然后replacationController会自动给我启动一个新的,新的pod的ip地址就会变,IP一变,全乱套了….比如你写了一个链接数据库的地方写了一个ip,pod一旦重启,所有数据库都连不上了….为了解决这个问题, 就引入了服务service,服务的意义就是:所有请求发给我,我给你去找具体的pod,我们就不用操心service怎么知道重启后的pod的新IP了(其实很简单,selector,每个pod都有一个label,如论怎么重启,新建,label不变,service就通过label来查找相应的pod的)
对应的pod:
1 2 3 4 5 6 7 8 9 |
kubectl get pod NAME READY STATUS RESTARTS AGE frontend-38h26 1/1 Running 0 22m frontend-980lq 1/1 Running 0 22m frontend-vzx01 1/1 Running 0 22m redis-master-fcerb 1/1 Terminating 0 3h redis-master-wwqp9 1/1 Running 0 27m redis-slave-pz18v 1/1 Running 0 24m redis-slave-rvznx 1/1 Running 0 24m |
同理:redis-slave ,frontend
然后,最重要是程序如何调用这些服务的IP
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
cat guestbook.php <? set_include_path('.:/usr/local/lib/php'); error_reporting(E_ALL); ini_set('display_errors', 1); require 'Predis/Autoloader.php'; Predis\Autoloader::register(); if (isset($_GET['cmd']) === true) { $host = 'redis-master'; if (getenv('<strong>GET_HOSTS_FROM</strong>') == 'env') { $host = getenv('<strong>REDIS_MASTER_SERVICE_HOST</strong>'); } header('Content-Type: application/json'); if ($_GET['cmd'] == 'set') { $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => $host, 'port' => 6379, ]); $client->set($_GET['key'], $_GET['value']); print('{"message": "Updated"}'); } else { $host = 'redis-slave'; if (getenv('GET_HOSTS_FROM') == 'env') { $host = getenv('<strong>REDIS_SLAVE_SERVICE_HOST</strong>'); } $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => $host, 'port' => 6379, ]); $value = $client->get($_GET['key']); print('{"data": "' . $value . '"}'); } } else { phpinfo(); } ?> |
其实pod之间是通过环境变量来知道服务的ip地址的,因为可能你服务是在pod创建之后才创建的服务,而且IP随机的,我们没法提前写好,所以,每当有一个新的服务创建的时候,在所有pod中增增加一系列的环境变量,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
env |grep -i redis REDIS_SLAVE_PORT_6379_TCP=tcp://10.254.3.44:6379 REDIS_SLAVE_SERVICE_HOST=10.254.3.44 REDIS_SLAVE_PORT=tcp://10.254.3.44:6379 REDIS_MASTER_PORT_6379_TCP_ADDR=10.254.43.174 REDIS_MASTER_PORT_6379_TCP=tcp://10.254.43.174:6379 REDIS_SLAVE_PORT_6379_TCP_PROTO=tcp REDIS_MASTER_SERVICE_PORT=6379 REDIS_SLAVE_SERVICE_PORT=6379 REDIS_MASTER_SERVICE_HOST=10.254.43.174 REDIS_SLAVE_PORT_6379_TCP_ADDR=10.254.3.44 REDIS_MASTER_PORT_6379_TCP_PORT=6379 REDIS_SLAVE_PORT_6379_TCP_PORT=6379 REDIS_MASTER_PORT_6379_TCP_PROTO=tcp REDIS_MASTER_PORT=tcp://10.254.43.174:6379 |
这样,我们在程序里只需要调用REDIS_MASTER_PORT 这样环境变量就可以自动转换为对应的对的IP地址了
Latest posts by Zhiming Zhang (see all)
- aws eks node 自动化扩展工具 Karpenter - 8月 10, 2022
- ReplicationController and ReplicaSet in Kubernetes - 12月 20, 2021
- public key fingerprint - 5月 27, 2021