K8S集群内部的服务发现
早期是通过环境变量和查询 apiserver 来解决服务之间互相访问的。同一命名空间下所有 service 的 ip、端口等信息都会存在环境变量中,通过查询环境变量获取到要访问服务的ip和端口。
当同一命名空间下服务很多时,环境变量就会变得非常臃肿,不易维护。因此人们又相处了一种比较理想的方案——直接使用服务的名字访问服务。服务名称和ip之间通过DNS解析得到。K8S提供了kube-dns来提供DNS解析服务,但是CoreDNS更加好用个,现在已经去到了kube-dns。从K8S1.12开始,CoreDNS成了默认的DNS服务器。
rancher 环境中已经安装了 CoreDNS 服务,无需重复安装
kubeadm init --feature-gates=CoreDNS=true --启动CoreDNS
下载kubectl
可以通过以下步骤,增加yum库,然后在线安装
[root@xuegod63 ~]# tee /etc/yum.repos.d/kubernetes.repo << 'EOF'
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
[root@xuegod63 ~]# yum install -y kubectl
也可以直接将下载好的kubectl 复制到服务器
并增加执行权限
chmod u+x kubectl
创建kubectl配置文件
按照提示把如下配置文件内容复制到rancher服务器的 ~/kub/config位置。
[root@host11 ~]# mkdir ~/.kube
[root@host11 ~]# cd ~/.kube
//rz 将文件赋值到该目录
测试kube命令
可以获取到节点信息
[root@host11 ~]# ./kubectl get node
NAME STATUS ROLES AGE VERSION
host12 Ready controlplane,etcd,worker 168m v1.20.8
说明
nginx 和php 在不同的pod中,必须吧nginx 网站根共享给php所在的pod(服务器),且路径相同,然后nginx将请求路径转发给php,php通过路径在相同的目录中找到文件并解析执行。
nfs就是用来让不同服务器共享文件目录的。
创建数据卷
//创建目录
[root@host11 ~]#mkdir -p /web/{html,data
[root@host11 ~]# vi /etc/exports //设置 目录的权限
/web/html *(rw,no_root_squash)
/web/data *(rw,no_root_squash)
//* 任何人 rw 读写 任何人都可以读写目录下的文件
//no_root_squash 当 root 时,其权限将被转换成为匿名
//使用者,通常它的 UID 与 GID,都会变成 nobody 身份
[root@host11 ~]# yum -y install nfs-utils rpcbind --安装nfs 及 相关服务
[root@host11 ~]# systemctl enable --now rpcbind --启动服务 并设置自启动
[root@host11 ~]# systemctl enable --now nfs
PersistenVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
PersistentVolumeClaim(PVC):让用户不需要关心具体的 Volume 实现细节。
总的来说,PV 是提供者,PVC 是消费者,消费的过程就是绑定、调用。容器与 PV、PVC 之间的关系,可以如下图所示,逐级调用达到复用和解耦的目的。
# tar -zvxf lnmp-v9.tar.gz --将文件上传并解压
#unzip ecshop.zip --解压ecshop文件 商城文件
[root@host11 lnmp]# ll
total 63668
drwxr-xr-x 2 root root 24 Dec 21 2020 conf
drwxr-xr-x 18 root root 4096 Dec 5 2018 ecshop
-rw-r--r-- 1 root root 65163191 Apr 18 2019 ecshop.zip
-rw-r--r-- 1 root root 936 Dec 22 2020 mysql-deployment.yaml
-rw-r--r-- 1 root root 202 Aug 4 2020 mysql-svc.yaml
drwxr-xr-x 2 root root 24 Dec 21 2020 nginx
-rw-r--r-- 1 root root 733 Mar 16 23:54 nginx-deployment.yaml
-rw-r--r-- 1 root root 212 Aug 4 2020 nginx-svc.yaml
drwxr-xr-x 2 root root 24 Dec 21 2020 php
-rw-r--r-- 1 root root 954 Mar 17 00:14 php-deployment.yaml
-rw-r--r-- 1 root root 149 Aug 4 2020 php-svc.yaml
-rw-r--r-- 1 root root 432 Mar 16 23:55 pv.yaml
mv ecshop/* /web/html/ //将商城项目文件辅导 web/html目录
定义PV和PVC
[root@host11 lnmp]# vi /root/lnmp/pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv --pvname
labels:
apps: mysql-pv
spec:
capacity:
storage: 5Gi --pv大小
accessModes:
- ReadWriteMany --可读可写多客户端挂载
nfs:
path: /web/data --nfs路径
server: 192.168.10.11 --nfs ip
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv
labels:
apps: web-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
path: /web/html
server: 192.168.1.63
创建 pv :pv.yml中一共创建了 2 个 pv 分别是 mysql-pv、web-pv
pv 权限说明
ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
ReadWriteMany(RWX):读写权限,可以被多个节点挂载
[root@host11 ~]# ./kubectl apply -f lnmp/pv.yaml
persistentvolume/mysql-pv created
persistentvolume/web-pv created
PV 描述的是持久化存储卷,主要定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。
PVC 描述的是 Pod 所希望使用的持久化存储的属性,比如,Volume 存储的大小、可读写权限等等。
使用过程是: nfs→pv→pvc→volume→volumeMount to path
编辑php-deployment.yaml文件
[root@host11 ~]# vi ~/lnmp/php-deployment.yaml
---
apiVersion: apps/v1 ---定义Deployment
kind: Deployment
metadata:
name: php-server
labels:
name: php-server
spec:
replicas: 1
selector:
matchLabels:
app: php-server
template:
metadata: ---------------------------定义POD
labels:
app: php-server
spec:
containers:
- name: php-server ----定义容器镜像
image: php:v1
imagePullPolicy: IfNotPresent
volumeMounts: ----将php-data卷 挂载到 /var/www/html
- name: php-data
mountPath: /var/www/html/
ports:
- containerPort: 9000 -------容器端口
lifecycle:
postStart:
exec: -----定义容器准备就绪后执行命令,yum方式安装的php-fpm默认用户为apache
-----php-data卷挂载到容器后,默认root用户可读可写,所以容器准备就绪后进行权限修改
command: [ "/bin/bash","-c","chown apache:apache /var/www/html -R" ]
volumes:
- name: php-data --------web-pvc 绑定到php-data卷
persistentVolumeClaim:
claimName: web-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-pvc -----创建web-pvc
labels:
app: php-server ----
spec:
accessModes: ---访问控制策略
- ReadWriteMany
resources:
requests:
storage: 1Gi --大小
selector:
matchLabels:
apps: web-pv 绑定web-pv
部署 php-deployment
[root@host11 ~]# ./kubectl apply -f lnmp/php-deployment.yaml
deployment.apps/php-server created
persistentvolumeclaim/web-pvc created
[root@host11 ~]# ./kubectl get pod
NAME READY STATUS RESTARTS AGE
php-server-f755868c8-94qjp 0/1 ContainerCreating 0 50s
部署php-svc
[root@host11 ~]# vi lnmp/php-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: php
spec:
ports:
- name: php
port: 9000
protocol: TCP
selector:
app: php-server
[root@host11 ~]# ./kubectl apply -f lnmp/php-svc.yaml
service/php created
配置文件
[root@host11 ~]# vi /root/lnmp/conf/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
index index.php;
}
location ~ \.php$ {
# root html;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
include fastcgi_params;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
nginx 的站点根目录是/usr/share/nginx/html 而 php 的解析目录是/var/www/html/两者仅仅是挂载到容器中的路径不一样,但是同源(实际都指向nfs中的内容)。fastcgi_pass 指定后端 php 解析地址时只需要指定php-svc 的名称即可,查看 svc 名称方式如下
[root@host11 ~]# ./kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 443/TCP 3h40m
php ClusterIP 10.43.217.222 9000/TCP 4m55s
ConfigMap 创建 nginx 配置文件
ConfigMap 简单介绍:ConfigMap 是 k8s 中非常重要的一个资源对象,简称 cm,常用于向容器中注入配置文件等操作,不仅可以保存单个属性值,也可以保存整个配置文件
语法格式: kubectl create configmap name --from-file=path
[root@host11 ~]# ./kubectl create configmap lnmp-nginx-config --from-file=/root/lnmp/conf/nginx.conf
configmap/lnmp-nginx-config created
[root@host11 ~]#
创建 nginx-deployment
[root@host11 ~]# vi lnmp/nginx-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-shop
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-shop
spec:
selector:
matchLabels:
app: nginx-shop
replicas: 1
template:
metadata:
labels:
app: nginx-shop
spec:
containers:
- name: nginx-shop
image: nginx:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: nginx-data
mountPath: /usr/share/nginx/html
- name: nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-data
persistentVolumeClaim:
claimName: web-pvc
- name: nginx-conf
configMap:
name: lnmp-nginx-config
部署 nginx
[root@host11 ~]# ./kubectl apply -f lnmp/nginx-deployment.yaml
deployment.apps/nginx-shop created
创建 nginx-svc
[root@host11 ~]# vi lnmp/nginx-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: nginx-shop
spec:
type: NodePort
ports:
- name: nginx
port: 80
protocol: TCP
targetPort: 80
nodePort: 30010
selector:
app: nginx-shop
[root@host11 ~]# ./kubectl apply -f lnmp/nginx-svc.yaml
service/nginx-shop created
访问 http://192.168.12.12:30010/install/index.php 看到了网站 如下:
看到安装界面表示 php 解析正确没有问题。现在不要部署网站,因为还没有安装数据库了
[root@host11 ~]# vi lnmp/mysql-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: default
labels:
k8s-app: mysql
spec:
selector:
matchLabels:
k8s-app: mysql
replicas: 1
template:
metadata:
labels:
k8s-app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
protocol: TCP
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
labels:
k8s-app: mysql
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
selector:
matchLabels:
apps: mysql-pv
mysql 容器中存在初始化脚本,使用 MYSQL_ROOT_PASSWORD 变量配置 mysql 登录密码
[root@host11 ~]# ./kubectl apply -f lnmp/mysql-deployment.yaml
deployment.apps/mysql created
persistentvolumeclaim/mysql-pvc created
创建 mysql-svc
[root@host11 ~]# vi lnmp/mysql-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
k8s-app: mysql
spec:
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
selector:
k8s-app: mysql
[root@host11 ~]# ./kubectl apply -f lnmp/mysql-svc.yaml
service/mysql created
安装完数据库就可以 安装php网站了
发布服务是通过反向代理实现的,也就是通过 nginx 反向代理我们 k8s 中的服务,nginx 并不能实时监测我们后端pod 的变化,比如增加或减少后端服务需要手工修改 nginx 配置,而 ingress 有一个监听器可以通过监听 kube-apiserver 来感知后端的 servcice、pod 变化。然后根据 ingress 的配置将后端信息更新给我们的反向代理。
工作原理:域名解析指向集群边缘节点(ingress代理),然后 ingress 匹配域名规则将请求转发至对应的服务
边缘节点
边缘节点是指我们 k8s 集群中对外提供服务的节点,因为 k8s 集群如果每一台主机都拥有公网 IP 其实是没有必要的,通常我们只需要边缘节点能够对外提供服务就可以了。此时我们发布服务时只要把域名解析指向边缘节点的 ip 就可以访问 k8s 中的服务。
rancher 中自带了服务发布的功能,是通过 nginx 实现的,如果是自建的 k8s 集群则建议使用Traefik。
创建 ingress 规则
本地hosts文件配置域名解析
访问 shop.com可以正常访问到,系统如下: