一、日志收集案例-容器内置日志收集
在容器内置日志收集服务进程,收集当前容器的业务容器日志等。
1、构建包含 filebeat 的业务镜像
Dockerfile
#tomcat web1
FROM y73.harbor.com/y73/tomcat-base:v8.5.43
ADD catalina.sh /apps/tomcat/bin/catalina.sh
ADD server.xml /apps/tomcat/conf/server.xml
#ADD myapp/* /data/tomcat/webapps/myapp/
ADD myapp.tar.gz /data/tomcat/webapps/myapp/
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD filebeat.yml /etc/filebeat/filebeat.yml
RUN chown -R tomcat.tomcat /data/ /apps/
#ADD filebeat-7.5.1-x86_64.rpm /tmp/
#RUN cd /tmp && yum localinstall -y filebeat-7.5.1-amd64.deb
EXPOSE 8080 8443
CMD ["/apps/tomcat/bin/run_tomcat.sh"]
build-command.sh
root@k8s-deploy:/yaml/20220821/ELK cases/3.container-filebeat-process/1.webapp-filebeat-image-Dockerfile# cat build-command.sh
#!/bin/bash
TAG=$1
docker build -t y73.harboe.com/y73/tomcat-app1:${TAG} .
#sleep 3
docker push y73.harboe.com/y73/tomcat-app1:${TAG}
#nerdctl build -t y73.harboe.com/y73/tomcat-app1:${TAG} .
#nerdctl push y73.harboe.com/y73/tomcat-app1:${TAG}
filebeat.yml:filebeat 配置文件,定义如何从容器拿日志以及传给 kafka
root@k8s-deploy:/yaml/20220821/ELK cases/3.container-filebeat-process/1.webapp-filebeat-image-Dockerfile# vim filebeat.yml
filebeat.inputs:
- type: log
enabled: true # 是否启用
paths:
- /apps/tomcat/logs/catalina.out # 容器内的启动日志路径
fields:
type: filebeat-tomcat-catalina
- type: log
enabled: true
paths:
- /apps/tomcat/logs/localhost_access_log.*.txt # 容器内的访问日志路径
fields:
type: filebeat-tomcat-accesslog
filebeat.config.modules:
path: ${
path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
setup.kibana:
output.kafka:
hosts: ["192.168.0.125:9092"]
required_acks: 1
topic: "filebeat-magedu-app1"
compression: gzip
max_message_bytes: 1000000
#output.redis:
# hosts: ["172.31.2.105:6379"]
# key: "k8s-magedu-app1"
# db: 1
# timeout: 5
# password: "123456"
catalina.sh:tomcat 启动脚本,可以网上找模板,主要修改以下内容
JAVA_OPTS="-server -Xms1g -Xmx1g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled"
run_tomcat.sh:该脚本在容器内执行 tail -f
命令,使得 tomcat 独占前台;并在后台启动 filebeat
#!/bin/bash
#echo "nameserver 223.6.6.6" > /etc/resolv.conf
#echo "192.168.7.248 k8s-vip.example.com" >> /etc/hosts
/usr/share/filebeat/bin/filebeat -e -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat &
su - tomcat -c "/apps/tomcat/bin/catalina.sh start"
tail -f /etc/hosts
server.xml:自行定义 tomcat 访问路径,其他配置不变
<Host name="localhost" appBase="/data/tomcat/webapps" unpackWARs="false" autoDeploy="false">
执行构建脚本
./build-command.sh
2、部署 web 服务
允许一个 tomcat 业务应用,其中每个 Pod 只有一个容器,每个容器内置 filebeat 进程
root@k8s-deploy:/yaml/20220821/ELK cases/3.container-filebeat-process# vim 3.tomcat-app1.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app1-filebeat-deployment-label
name: magedu-tomcat-app1-filebeat-deployment
namespace: magedu
spec:
replicas: 5
selector:
matchLabels:
app: magedu-tomcat-app1-filebeat-selector
template:
metadata:
labels:
app: magedu-tomcat-app1-filebeat-selector
spec:
containers:
- name: magedu-tomcat-app1-filebeat-container
image: y73.harboe.com/y73/tomcat-app1:v1-filebeat
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 300m
memory: "256Mi"
requests:
cpu: 300m
memory: "256Mi"
创建 service 允许从外部访问 tomcat
root@k8s-deploy:/yaml/20220821/ELK cases/3.container-filebeat-process# vim 4.tomcat-service.yaml
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-tomcat-app1-filebeat-service-label
name: magedu-tomcat-app1-filebeat-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30092
selector:
app: magedu-tomcat-app1-filebeat-selector
如果是以 Pod 形式部署 filebeat (即在k8s集群层面部署)还需要给 filebeat 定义各种权限,本例是内置在容器内部所以不需要
root@k8s-deploy:/yaml/20220821/ELK cases/3.container-filebeat-process# vim 2.filebeat-serviceaccount.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: filebeat-serviceaccount-clusterrole
labels:
k8s-app: filebeat-serviceaccount-clusterrole
rules:
- apiGroups: [""] # "" indicates the core API group
resources:
- namespaces
- pods
- nodes
verbs:
- get
- watch
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: filebeat-serviceaccount-clusterrolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: magedu
roleRef:
kind: ClusterRole
name: filebeat-serviceaccount-clusterrole
apiGroup: rbac.authorization.k8s.io
3、修改 logstash 配置文件
和上文一样,在 /etc/logstash/conf.d/
目录新增 logstash 配置文件,定义 filebeat 如何将收集的日志传给 ES。
root@logsatsh01:/etc/logstash/conf.d# vim filebeat-log-to-es.conf
input {
kafka {
bootstrap_servers => "192.168.0.125:9092,192.168.0.126:9092,192.168.0.127:9092"
topics => ["filebeat-magedu-app1"]
codec => "json"
}
}
output {
if [fields][type] == "filebeat-tomcat-catalina" {
elasticsearch {
hosts => ["192.168.0.122:9200","192.168.0.123:9200","192.168.0.124:9200"]
index => "filebeat-tomcat-catalina-%{+YYYY.MM.dd}"
}}
if [fields][type] == "filebeat-tomcat-accesslog" {
elasticsearch {
hosts => ["192.168.0.122:9200","192.168.0.123:9200","192.168.0.124:9200"]
index => "filebeat-tomcat-accesslog-%{+YYYY.MM.dd}"
}}
}
之后重启 logstash 并查看日志观察有无报错
root@logsatsh01:/etc/logstash/conf.d# systemctl restart logstash.service
root@logsatsh01:/etc/logstash/conf.d# tail -f /var/log/logstash/logstash-plain.log
4、进行验证
1、kafka 客户端验证
2、Elasticsearch
没有启动日志索引,可以增加副本数量或者进入 Pod 直接往启动日志里写数据
3、kibana
操作步骤和上面一样
二、overlay与underlay通信总结
网络二层通信
在计算机网络中,网络二层通信指的是在数据链路层(也称为第二层)进行的通信。数据链路层的主要功能是将数据帧从一个网络节点传输到另一个网络节点。
数据链路层的实现通常需要两个重要的协议:MAC(Media Access Control,媒体访问控制)协议和LLC(Logical Link Control,逻辑链路控制)协议。
MAC协议是数据链路层中最重要的协议之一,它规定了数据帧的格式和传输方式。MAC协议使用一个唯一的地址(MAC地址)来标识每个网络设备。当一台设备要向另一台设备发送数据帧时,它首先会在网络中广播一个请求信号,请求其他设备暂停发送数据。这个过程称为“争用”,只有一个设备能够赢得争用并获得发送数据的权利。一旦设备获得发送数据的权利,它会将数据帧发送到目标设备的MAC地址。
LLC协议则负责控制数据帧的流量,以及提供一些错误检测和纠正的功能。它定义了一些逻辑连接类型和控制消息,用于控制数据链路层的数据传输和错误处理。
总的来说,网络二层通信通过MAC协议和LLC协议实现。在这个过程中,每个设备都有一个唯一的MAC地址,数据帧会根据目标设备的MAC地址进行路由,而LLC协议则负责控制数据帧的传输和错误处理,确保数据的可靠性和完整性。
VLAN
VLAN(Virtual Local Area Network,虚拟局域网)是一种逻辑上的网络,将一个物理局域网(LAN)划分为多个逻辑子网。这些逻辑子网可以跨越多个物理设备,但是它们在逻辑上被视为独立的网络。
VLAN的作用主要有以下几个方面:
- 增强网络安全性:VLAN可以将不同的用户和设备隔离在不同的逻辑子网中,以减少网络攻击和数据泄露的风险。
- 简化网络管理:通过VLAN,管理员可以将不同的用户和设备划分到不同的逻辑子网中,从而更容易管理网络和配置网络策略。
- 提高网络性能:VLAN可以将网络流量隔离在不同的逻辑子网中,从而减少网络拥塞和冲突,提高网络性能和可靠性。
- 支持虚拟化:VLAN可以为不同的虚拟机创建不同的逻辑子网,从而实现虚拟机之间的隔离和互访。
实现VLAN通常需要交换机或路由器等设备支持VLAN技术,并进行相应的配置。在配置VLAN时,管理员需要为每个VLAN分配一个唯一的VLAN ID,以及为每个端口配置相应的VLAN成员关系。这样,当数据包到达交换机或路由器时,设备就可以根据VLAN ID进行路由,将数据包转发到正确的VLAN中。
VXLAN
VXLAN(Virtual Extensible LAN)是一种虚拟化技术,用于扩展数据中心的二层网络。VXLAN通过在传统的Ethernet帧上封装一个额外的头部,将一个虚拟网络的二层数据包从底层物理网络中隔离出来,从而实现跨物理网络的虚拟网络通信。
VXLAN的主要作用如下:
- 扩展网络:VXLAN允许在数据中心内创建更多的虚拟网络,使得网络能够更加灵活地满足不同的业务需求,同时减少网络中的广播和多播流量,提高网络性能和可靠性。
- 隔离虚拟网络:VXLAN通过封装和解封装的过程,将不同的虚拟网络之间的流量相互隔离,避免虚拟网络之间的冲突和干扰,从而提高网络安全性。
- 支持跨数据中心:VXLAN可以扩展到多个数据中心,允许在不同的数据中心之间建立虚拟网络通信,实现数据中心间的互连。
VXLAN的实现通常需要三个组成部分:
- VXLAN网络标识符(VNI):它是一个24位的标识符,用于唯一地标识一个VXLAN虚拟网络。
- VTEP(VXLAN Tunnel End Point):它是VXLAN网络的出入口,负责将数据帧封装到VXLAN报文中,并将其发送到目的地。VTEP可以是一个物理设备或虚拟设备。
- VTEP之间的通信机制:VTEP之间需要进行通信,以实现虚拟网络之间的互通。VXLAN通常使用UDP作为底层传输协议,通过在UDP报文中封装VXLAN报文,从而实现VTEP之间的通信。
总的来说,VXLAN是一种虚拟化技术,可以扩展数据中心的二层网络,并提高网络的灵活性、可靠性和安全性。VXLAN通过在数据帧上封装额外的头部来实现,需要VTEP之间的通信机制来支持虚拟网络之间的互通。
overlay
Overlay网络模型是一种在宿主机网络之上创建虚拟网络的方式。在这种模型下,Kubernetes会在每个节点上运行一个代理程序,这个代理程序会创建一个虚拟的网络层,其中包含了所有运行在该节点上的容器。当一个容器需要与另一个容器通信时,它会发送一个网络包到虚拟网络中的目标地址,然后代理程序会将该包转发到目标容器。
Overlay网络模型的优点在于它可以允许跨主机的容器通信,这是因为虚拟网络层被建立在宿主机网络之上。此外,它也可以提供一些额外的网络安全性,比如在虚拟网络层上加密数据包等。
然而,Overlay网络模型的缺点在于它需要额外的网络开销,因为代理程序需要在虚拟网络层和宿主机网络之间进行转发。这会导致一些性能上的问题,并且也需要消耗额外的计算资源。
underlay
Underlay网络模型是一种直接使用宿主机网络的方式。在这种模型下,Kubernetes会在每个节点上创建一个网桥,并为每个容器分配一个独立的IP地址。当一个容器需要与另一个容器通信时,它会将网络包发送到目标IP地址,然后网桥会将该包转发到目标容器。
Underlay网络模型的优点在于它可以提供更快的网络传输速度,因为网络包不需要经过代理程序的转发。此外,它也不需要消耗额外的计算资源,因为它直接使用宿主机网络。
然而,Underlay网络模型的缺点在于它不能够支持跨主机的容器通信,因为每个容器只有一个独立的IP地址。此外,它也不提供额外的网络安全性,因为数据包在宿主机网络上传输时没有加密等保护。
Underlay网络模型在实现上有不同的方式,其中两种常用的方式是Macvlan和Ipvlan。
- Macvlan
Macvlan是一种将物理网卡的MAC地址与容器的虚拟网卡一一映射的方式,实现容器直接使用物理网络进行通信。这种方式在容器与物理网络之间建立了一条直接的通信路径,因此网络性能较高。
Macvlan共有4种实现方式:
- Private Macvlan:在物理网卡上创建一组虚拟接口,每个虚拟接口与一个容器的虚拟接口绑定,容器可以直接使用物理网络进行通信。这种方式可以实现容器与物理网络的完全隔离。
- VEPA(Virtual Ethernet Port Aggregator)Macvlan:在交换机中创建VEPA端口,将VEPA端口绑定到物理网卡上,然后将容器的虚拟接口绑定到VEPA端口上,容器可以直接使用物理网络进行通信。这种方式可以使容器具有直接的MAC地址和IP地址,并且可以与物理网络中的其他设备直接通信。
- Passthru Macvlan:在物理网卡上创建一个虚拟接口,然后将这个虚拟接口直接暴露给容器,容器的虚拟接口直接绑定到这个虚拟接口上。这种方式可以使容器具有直接的MAC地址和IP地址,并且可以与物理网络中的其他设备直接通信。
- Bridge Macvlan:在物理网卡上创建一个Linux网桥,然后将这个网桥与物理网卡进行桥接,容器的虚拟接口绑定到这个网桥上,容器可以直接使用物理网络进行通信。这种方式可以使容器具有直接的MAC地址和IP地址,并且可以与物理网络中的其他设备直接通信。
- Ipvlan
Ipvlan是一种将物理网络的IP地址与容器的虚拟网卡一一映射的方式,实现容器直接使用物理网络进行通信。与Macvlan不同的是,Ipvlan不需要映射MAC地址,而是将容器虚拟接口直接绑定到物理网络的接口上。
Ipvlan分为两种实现方式:
- L2 Ipvlan:将容器的虚拟接口绑定到物理网络的接口上,容器可以直接使用物理网络进行通信。这种方式可以实现容器与物理网络的完全隔离。
- L3 Ipvlan:在L2 Ipvlan的基础上,为每个容器分配一个唯一的IP地址,并将这个IP地址绑定到容器的虚拟接口上。这种方式可以使容器具有直接的IP地址,并且可以直接从外部网络访问容器。
k8s Pod 通信
underlay案例
首先进行IP地址规划,本例中我的宿主机网络是192.168.0.0/24。划分三个子网,分别给node节点、service 和 Pod 使用。
假设要将 192.168.0.0/24 这个网段划分成 3 个子网,则需要重新分配 IP 地址范围、子网掩码、广播地址和可用地址数量等参数。下面是一种可能的划分方式:
- 子网 1:node 节点使用
- IP 地址范围:192.168.0.1 - 192.168.0.63
- 子网掩码:255.255.255.192 (/26)
- 广播地址:192.168.0.63
- 可用地址数量:62
- 子网 2:service 使用
- IP 地址范围:192.168.0.64 - 192.168.0.127
- 子网掩码:255.255.255.192 (/26)
- 广播地址:192.168.0.127
- 可用地址数量:62
- 子网 3:Pod 使用
- IP 地址范围:192.168.0.128 - 192.168.0.254
- 子网掩码:255.255.255.128 (/25)
- 广播地址:192.168.0.255
- 可用地址数量:126
1、环境准备
1、安装docker
使用 kubeadm 部署一套新的 k8s 集群,首先安装 docker 作为运行时。
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce
docker 参数优化,使用镜像加速并把 Cgroup Driver 改为 systemd 。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://gjsamcgt.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2、安装 cri-dockerd
k8s不再直接支持 docker ,需要安装 cri-dockerd。
cri-dockerd
是一个实验性的容器运行时,它将 Docker 容器引擎 (dockerd
) 作为 CRI (Container Runtime Interface) 的实现。CRI 是 Kubernetes 使用的标准容器运行时接口,它定义了 Kubernetes 如何与容器运行时交互,包括如何启动、停止、监视容器等。
通过使用 cri-dockerd
,Kubernetes 可以使用 Docker 作为底层容器引擎来运行容器。cri-dockerd
的实现方式是使用 Docker 引擎作为容器运行时,并将其作为 CRI 插件实现。这样,Kubernetes 可以像使用其他 CRI 兼容的容器运行时一样,使用 Docker 引擎来运行容器。
需要注意的是,cri-dockerd
是一个实验性的项目,不建议在生产环境中使用。它可能会受到 Docker 引擎自身的限制和限制,同时也可能会受到 Kubernetes 和 CRI 规范的限制。因此,在选择容器运行时时,建议使用官方支持的容器运行时,如 Containerd 或 CRI-O。
root@k8s-node3:~# wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.1/cri-dockerd-0.3.1.amd64.tgz
root@k8s-node3:~# tar xvf cri-dockerd-0.3.1.amd64.tgz
cri-dockerd/
cri-dockerd/cri-dockerd
root@k8s-node3:~# cp cri-dockerd/cri-dockerd /usr/local/bin
root@k8s-node3:~# cri-dockerd --version
cri-dockerd 0.3.1 (7e528b98)
配置 cri-docker.service 文件。
其中,ExecStart
参数指定了启动 cri-dockerd
的命令行参数,包括 --network-plugin=cni
表示使用 CNI 网络插件、--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7
表示使用阿里云镜像仓库中的 pause:3.7
镜像作为 Pod 的 Infra Container。
root@k8s-master:~# vim /lib/systemd/system/cri-docker.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7
ExecReload=/bin/kill -S HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
配置 cri-docker.socket文件.
该 socket 文件用于与 cri-dockerd
服务进行通信,让 kubelet 通过 CRI 调用 Docker API。当 kubelet 启动时,它将使用该 socket 文件建立到 cri-dockerd
服务的连接。其他组件可以通过连接到该 socket 文件来使用 Docker 容器运行时的功能。
root@k8s-node3:~# vim /lib/systemd/system/cri-docker.socket
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-dockerd.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=socket.target
启动
systemctl daemon-reload && systemctl restart cri-docker.service && systemctl enable cri-docker.service && systemctl enable --now cri-docker.socket
2、部署集群
1、使用 kubeadm 部署集群
所有节点安装 kubectl、kubelet、kubeadm。本例使用1.24.4版本
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt install -y kubeadm=1.24.4-00 kubelet=1.24.4-00 kubectl=1.24.4-00
# 验证版本
root@k8s-node3:~# kubeadm version
kubeadm version: &version.Info{
Major:"1", Minor:"24", GitVersion:"v1.24.4", GitCommit:"95ee5ab382d64cfe6c28967f36b53970b8374491", GitTreeState:"clean", BuildDate:"2022-08-17T18:52:53Z", GoVersion:"go1.18.5", Compiler:"gc", Platform:"linux/amd64"}
2、初始化集群
1、镜像准备
在 master 节点提前下载好需要的镜像
# kubeadm config images list --kubernetes-version v1.24.4
k8s.gcr.io/kube-apiserver:v1.24.4
k8s.gcr.io/kube-controller-manager:v1.24.4
k8s.gcr.io/kube-scheduler:v1.24.4
k8s.gcr.io/kube-proxy:v1.24.4
k8s.gcr.io/pause:3.7
k8s.gcr.io/etcd:3.5.3-0
k8s.gcr.io/coredns/coredns:v1.8.6
将其替换成国内的源,并编辑脚本。
# vim images-down.sh
#!/bin/bash
docker pull registry.