一、整體說明
1.1、背景說明
當前微服務架構有多種模式,需要對其選型進行集成及實施:
-
方案一:Java世界的微服務Spring Cloud
在Java世界里SpringCloud,已經成為微服務開發的主流技術棧,其核心組件如下圖所示。
缺點是和java的綁定關系太強,我們的系統有多種語言,基本上不適合。
-
方案二:微軟雲Service Fabric
如果你是基於微軟雲構建系統,那么恭喜你,你直接選擇Service Fabric,可以為你節省半年到1年的架構開發工作!
缺點是如果你不是基於微軟雲構建的系統,那么,則很難對其進行實施
-
方案三:自研
微服務的注冊和發現 :集成諸如Zookeeper之類的服務
微服務的部署和彈性伸縮: docker + Kubernetes
微服務間的通訊:Http WebApi
微服務間通訊的效率:低,有級聯崩潰的可能性
微服務間的事務性(ACID):CAP或異步通訊+人工處理
微服務的對外網關、限流熔斷:nginx/Kubernetes/IIS/自己輕量包裝
微服務的全局配置:DB/Redis/zookeeper
微服務的認證授權(OAuth2):IdentityServer
微服務間的異步通訊、消息:RabbitMq等類似組件
微服務的日志: log4net /Rabbitmq
微服務的監控:HealthCheck接口
缺點是落地及開發實施較難,周期較長,且質量無從把控
-
方案四:kubernets+istio方案
這里不作過多闡述,推存文章:
https://blog.csdn.net/gui951753/article/details/81543545
最終我們選定了此種方案
1.2、整體架構
如下圖所示:
如圖所示,接下來會一步一步將架構進行落地實施。
二、Kubernetes安裝與配置
首先准備兩台CentOS8.0服務器,首先在主服務器進行配置安裝(作為Master節點運行)
2.1、安裝docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo(中央倉庫)
#可以查看所有倉庫中所有docker版本,並選擇特定版本安裝
yum list docker-ce --showduplicates | sort -r
#安裝docker
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
yum -y install ./containerd.io-1.2.13-3.1.el7.x86_64.rpm
yum -y install docker-ce-3:19.03.13-3.el8
#啟動Docker,然后加入開機啟動
systemctl start docker
systemctl start docker
systemctl enable docker
2.2、安裝dotnet
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
sudo yum install dotnet-sdk-3.1
#解決圖片字體的依賴包
sudo yum install https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/l/libgdiplus-6.0.4-3.el8.x86_64.rpm
其它問題
A fatal error occurred.
A fatal error occurred. The required library libhostfxr.so could not be found.
or
A fatal error occurred. The folder [/usr/share/dotnet/host/fxr] does not exist.
or
A fatal error occurred, the folder [/usr/share/dotnet/host/fxr] does not contain any version-numbered child folders.
What's going on?
This generally happens when two Linux package repositories provide .NET packages. While Microsoft provides a Linux package repository to source .NET packages, some Linux distributions also provide .NET packages, such as:
Arch
CentOS
Fedora
RHEL
Mixing .NET packages from two different sources will most likely lead to issues since the packages may place things at different paths, and may be compiled differently.
解決辦法:
sudo dnf remove packages-microsoft-prod
sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
檢查安裝是否正確
dotnet --verion
2.3、安裝java
yum安裝:
yum -y remove java-1.8.0-openjdk*
yum -y remove tzdata-java.noarch
yum -y list java*
yum -y install java-1.8.0-openjdk
java -version
離線安裝:
wget https://download.oracle.com/otn/java/jdk/8u281-b09/89d678f2be164786b292527658ca1605/jdk-8u281-linux-x64.tar.gz?AuthParam=1618390354_4042a0e96e56c4c30460d13052d6756a
tar -zxvf jdk-8u281-linux-x64.tar.gz
vim /etc/profile
export JAVA_HOME=/data/jdk1.8.0_281
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
ln -s /data/jdk1.8.0_281/bin/java /usr/bin/java
2.4、編譯成docker,發布到鏡像倉庫
首先需要在docker.io上面申請一個賬號,以.net core應用程序為例,進行docker鏡像的打包,后面會給出github用action編譯后自動推送到docker.io上。
libgdiplus在打包時最好盡量裝上,否則會報一些莫名其妙的錯誤,類似於:
System.DllNotFoundException: Unable to load shared library 'libgdiplus' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibgdiplus: cannot open shared object file: No such file or directory
的錯誤。
vim Dockerfile
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN apt-get update
RUN apt-get -y install libgdiplus
RUN apt-get -y install vim
RUN apt-get -y install net-tools
RUN apt-get -y install iputils-ping
RUN apt-get -y install telnet
RUN apt-get -y install procps
WORKDIR /app
COPY . .
EXPOSE 8000
ENTRYPOINT ["dotnet", "RoadFlow.WebApi.dll"]
開始打包並推送到倉庫:
docker build -t littlewrong/tw.bpm:v1.0.0 .
docker push littlewrong/tw.bpm:v1.0.0
此文件必須放在打包所在的項目文件夾中
2.5、安裝k8s_Master
#關閉防火牆
systemctl stop firewalld
systemctl disable firewalld
vim /etc/selinux/config
SELINUX=disabled
#修改 sysctl 配置
vim /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
sysctl --system
#關閉 swap
swapoff -a
vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
#kubernetes yum源
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
#指定安裝Kubernetes的版本(一定安裝1.18.0版本的)
yum -y install epel-release
yum clean all
yum makecache
yum install -y kubeadm-1.18.0-0 kubectl-1.18.0-0 kubelet-1.18.0-0
#拉取k8s的docker鏡像
kubeadm config images list
#編輯鏡像文件:
set ff=unix //設置為unix格式
./get_image_docker.sh 拉取鏡像
#初始化kubernetes
#pod-network 的IP千萬不要和局域網的IP重合,否則會造成pod內網不通外網的情況,一定切記切記
#另外特別注意--pod-network-cidr的網段必須和kube-flannel的網段地址要保持一樣,否則也會造成pod內部IP不通的情況,最好設成默認的10.244.0.0/16
kubeadm init --kubernetes-version=v1.18.0 --service-cidr=10.1.0.0/16 --pod-network-cidr=10.10.0.0/16 --image-repository=registry.aliyuncs.com/google_containers --ignore-preflight-errors=all
#單機版kubernetes為了運行Pod.需要刪除主機上的Train.允許master執行Pod.
kubectl taint nodes --all node-role.kubernetes.io/master-
kubectl taint nodes iz2vcf9v41doxowbcqr492z node-role.kubernetes.io/master=:NoSchedule
error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
vim /etc/profile
export KUBECONFIG=/etc/kubernetes/admin.conf
#立即生效
source /etc/profile
#部署flannel網絡,否則節點無法運行
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
docker pull quay.io/coreos/flannel:v0.12.0-amd64
kubectl apply -f kube-flannel.yml
kubectl get nodes
#配置訪問集群的,同時好需要執行如下命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#查詢執行錯誤
journalctl -f -u kubelet
docker images|grep flannel
systemctl restart kubelet
#卸載服務
kubeadm reset
2.6、安裝k8s_Node
#關閉防火牆
systemctl stop firewalld
systemctl disable firewalld
vim /etc/selinux/config
SELINUX=disabled
#修改 sysctl 配置
vim /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
sysctl --system
#關閉 swap
swapoff -a
vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
#kubernetes yum源
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
#指定安裝Kubernetes的版本(安裝1.18.0版本的)
yum -y install epel-release
yum clean all
yum makecache
yum install -y kubeadm-1.18.0-0 kubectl-1.18.0-0 kubelet-1.18.0-0
#拉取k8s的docker鏡像
kubeadm config images list
./k8s.sh
#創建token,加入集群
kubeadm token create --print-join-command
kubeadm join 192.168.0.120:6443 --token 382ywp.0k7ey52c7mombi20 \
--discovery-token-ca-cert-hash sha256:65c07b4f4e04484fffbc237eb00d5256a042346ce608cafd29c1425b197131cf
vim /etc/profile
export KUBECONFIG=/etc/kubernetes/admin.conf
#部署flannel網絡。
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
docker pull quay.io/coreos/flannel:v0.12.0-amd64
kubectl apply -f kube-flannel.yml
#查看節點的運行狀態
kubectl get nodes -o wide
#node節點執行:
mkdir -p $HOME/.kube
scp 192.168.0.120:/root/.kube/config $HOME/.kube/config
#查詢執行錯誤
journalctl -f -u kubelet
docker images|grep flannel
systemctl restart kubelet
#卸載服務
kubeadm reset
2.7、安裝k8s web管理面板
#執行yaml文件直接部署
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
#修改servcie部分
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort #修改為NodePort,映射到外部
ports:
- port: 443
targetPort: 8443
nodePort: 30443 #NodePort端口號
selector:
k8s-app: kubernetes-dashboard
kubectl apply -f recommended.yaml
#查看dashboard運行狀態,以deployment方式部署,運行2個pod及2個service:
kubectl -n kubernetes-dashboard get pods
kubectl -n kubernetes-dashboard get svc
#登錄dashboard
https://<any_node_ip>:30443
#Dashboard 支持 Kubeconfig 和 Token兩種認證方式,我們這里選擇Token認證方式登錄。
#創建dashboard-adminuser.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
#創建登錄用戶
kubectl apply -f dashboard-adminuser.yaml
#創建登錄token,把獲取到的Token復制到登錄界面的Token輸入框中,成功登陸dashboard
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
三、istio安裝與配置
Istio 使用功能強大的 Envoy 服務代理擴展了 Kubernetes,以建立一個可編程的、可感知的應用程序網絡。Istio 與 Kubernetes 和傳統工作負載一起使用,為復雜的部署帶來了標准的通用流量管理、遙測和安全性。
3.1、安裝istio
#下載istio:
https://github.com/istio/istio/releases/tag/1.8.6
#轉到istio包目錄
cd istio-1.8.6
#安裝目錄包含:
#samples/ 目錄下的示例應用程序
#bin/ 目錄下的 istioctl 客戶端二進制文件
#將 istioctl 客戶端加入搜索路徑(Linux or macOS)
export PATH=$PWD/bin:$PATH
#安裝istio
istioctl install --set profile=demo -y
#給命名空間添加標簽,指示 Istio 在部署應用的時候,自動注入 Envoy 邊車代理
#kubectl label namespace default istio-injection=enabled
#部署示例應用
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.0.0.212 <none> 9080/TCP 29s
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 25m
productpage ClusterIP 10.0.0.57 <none> 9080/TCP 28s
ratings ClusterIP 10.0.0.33 <none> 9080/TCP 29s
reviews ClusterIP 10.0.0.28 <none> 9080/TCP 29s
kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-558b8b4b76-2llld 2/2 Running 0 2m41s
productpage-v1-6987489c74-lpkgl 2/2 Running 0 2m40s
ratings-v1-7dc98c7588-vzftc 2/2 Running 0 2m41s
reviews-v1-7f99cc4496-gdxfn 2/2 Running 0 2m41s
reviews-v2-7d79d5bd5d-8zzqd 2/2 Running 0 2m41s
reviews-v3-7dbcdcbc56-m8dph 2/2 Running 0 2m41s
#重新運行前面的命令,在執行下面步驟之前,要等待並確保所有的 Pod 達到此狀態: 就緒狀態(READY)的值為 2/2 、狀態(STATUS)的值為 Running 。 基於你平台的不同,這個操作過程可能會花費幾分鍾的時間。
#把應用關聯到 Istio 網關
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
#確保配置文件沒有問題
istioctl analyze
✔ No validation issues found when analyzing namespace: default.
#設置網關入站端口
export PATH=/config/istio/istio-1.8.6/bin:$PATH
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT
#確保 IP 地址和端口均成功的賦值給了環境變量
echo "$GATEWAY_URL"
# 運行下面命令,獲取 Bookinfo 應用的外部訪問地址
echo "http://$GATEWAY_URL/productpage"
#把上面命令的輸出地址復制粘貼到瀏覽器並訪問,確認 Bookinfo 應用的產品頁面是否可以打開。
3.2、安裝kiali網格可視化管理
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system
#如果提示語法錯誤,則單獨將kiali的CRD文件獨立出來,進行apply create一下,到最后也沒明白為什么單獨可以,合在一個文件就不行
---
# Source: crds/crds.yaml
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: monitoringdashboards.monitoring.kiali.io
spec:
group: monitoring.kiali.io
names:
kind: MonitoringDashboard
listKind: MonitoringDashboardList
plural: monitoringdashboards
singular: monitoringdashboard
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
#訪問 Kiali 儀表板,同時需要修改Service的類別為NodePort,以支持外網訪問
istioctl dashboard kiali
3.3、安裝jaeger性能采集指標監控
#如前面安裝可以忽略此步
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system
#訪問儀表盤,同時需要修改Service的類別為NodePort,以支持外網訪問
istioctl dashboard jaeger
3.4、安裝Prometheus及Grafana應用程序指標監控
#如前面安裝可以忽略此步
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system
#驗證 prometheus 服務正在集群中運行
kubectl -n istio-system get svc prometheus
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus 10.59.241.54 <none> 9090/TCP 2m
#驗證 Grafana 服務正在集群中運行
kubectl -n istio-system get svc grafana
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana 10.59.247.103 <none> 3000/TCP 2m
#通過 Grafana UI 打開 Istio Dashboard,同時需要修改Service的類別為NodePort,以支持外網訪問
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000 &
在瀏覽器中訪問 http://localhost:3000/dashboard/db/istio-mesh-dashboard。
四、對接Samba&CIFS文件共享存儲
當應用服務打包成鏡像后,其會話狀態及文件存儲不能在單節點中進行存儲,需要由統一的服務進行接管,kubernetes提供CSI驅動將外部存儲提供給pod中使用,例如我們可以通過CSI驅動對接Samba/CIFS共享文件存儲,以達到文件共享訪問的目的。
首先需要安裝samba
#安裝samba(全安裝)
sudo dnf install samba samba-common samba-client
#客戶端安裝
yum install -y samba-client
#查看版本號
smbd -V
#編輯配置文件
vim /etc/samba/smb.conf
[global]
workgroup = WORKGROUP
server string = Samba Server %v
netbios name = centos-8
security = user
map to guest = bad user
dns proxy = no
[public]
path = /share
browsable =yes
writable = yes
guest ok = yes
read only = no
#運行測試命令
testparm
#啟動samba
sudo systemctl start smb
sudo systemctl enable smb
systemctl restart smb
systemctl status smb
#客戶端連接
smbclient //192.168.0.120/public -U root
ls //查看文件
get xxx.xxx //下載文件
put xxx.xxx //上傳文件
#掛載目錄,在指定服務器上執行
mount -t cifs //192.168.0.120/public /share -o username=root,password=xxxxxx
在 Kubernetes 中掛載 cifs 網絡文件共享協議的卷
Kubernetes提供了Flexvolume,這是一種插件機制,使用戶可以編寫自己的驅動程序。
Kubernetes 在默認的情況下在 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ 下搜索第三方插件。在該目錄下創建文件夾 fstab~cifs, 把 cifs 文件放到該文件夾下。fstab~cifs 將被映射為名為 fstab/cifs 的 flexvolume 插件。
VOLUME_PLUGIN_DIR="/usr/libexec/kubernetes/kubelet-plugins/volume/exec"
mkdir -p "$VOLUME_PLUGIN_DIR/fstab~cifs"
cd "$VOLUME_PLUGIN_DIR/fstab~cifs"
curl -L -O https://raw.githubusercontent.com/fstab/cifs/master/cifs
chmod 755 cifs
集群各節點都需要有以下 packages 環境:
mount.cifs:在 ubuntu 上 sudo apt install cifs-utils
jq:在ubuntu 上 sudo apt install jq
mountpoint:在ubuntu 上sudo apt install util-linux
base64: 在 ubuntu 上 sudo apt install coreutils (大多已默認安裝)
可以執行一下剛剛復制到
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/fstab~cifs
看是否安裝成功:./cifs init,成功會顯示“status”: "Success"。
echo -n username | base64
echo -n password | base64
#創建 cifs-secret.yml 文件:
apiVersion: v1
kind: Secret
metadata:
name: cifs-secret
namespace: default
type: fstab/cifs
data:
username: 'ZXhhbXBsZQ=='
password: 'bXktc2VjcmV0LXBhc3N3b3Jk'
#創建 Secret 資源
kubectl apply -f cifs-secret.yml
#使用命令 kubectl describe secret cifs-secret 檢測是否創建成功。
#最后在pod中掛載硬盤,創建twbpm.yml
apiVersion: apps/v1
kind: Deployment # 定義Kubernetes資源的類型為Deployment
metadata:
name: tw.bpm # 定義資源的名稱
namespace: application
labels:
app: tw.bpm
spec: # 定義資源的狀態。
replicas: 2 # 定義我們想運行多少個Pod,在這里我們希望運行2個
selector:
matchLabels: # 定義該部署匹配哪些Pod
app: tw.bpm
minReadySeconds: 5 # 可選,指定Pod可以變成可用狀態的最小秒數,默認是0
strategy: # 指定更新版本時,部署使用的策略
type: RollingUpdate # 策略類型,使用RollingUpdate可以保證部署期間服務不間斷
rollingUpdate:
maxUnavailable: 1 # 部署時最大允許停止的Pod數量(與replicas相比)
maxSurge: 1 # 部署時最大允許創建的Pod數量(與replicas相比)
template: # 用來指定Pod的模板,與Pod的定義類似
metadata:
labels: # 根據模板創建的Pod會被貼上該標簽,與上面的matchLabels對應
app: tw.bpm
spec:
containers:
- name: web
image: littlewrong/tw.bpm:1.0.20
imagePullPolicy: Always # 默認是IfNotPresent,如果設置成Always,則每一次部署都會重新拉取容器映像(否則,如果本地存在指定的鏡像版本,就不會再去拉取)
ports:
- containerPort: 8000
volumeMounts:
- name: twbpmshare
mountPath: /share
- name: app-bpmlogs
mountPath: /logs
- name: filebeat
image: littlewrong/filebeat:6.2.4
volumeMounts:
- name: app-bpmlogs
mountPath: /logs
volumes:
- name: twbpmshare
flexVolume:
driver: "fstab/cifs"
fsType: "cifs"
secretRef:
name: "cifs-secret"
options:
networkPath: "//192.168.0.120/public"
mountOptions: "dir_mode=0755,file_mode=0644,noperm"
- name: app-bpmlogs
emptyDir: {}
#flexVolume 為掛載的網絡硬盤,app-bpmlogs掛載的本pod的日志卷,這里可以忽略。
Pod 創建成功后,在 Pod 中啟動一個shell 查看網絡硬盤是否掛載成功。
kubectl exec -ti PodId /bin/sh
ls /share
五、日志搜索及管理
通常的方案有三種
- 每個app的鏡像中都集成日志收集組件
優點:部署方便,kubernetes的yaml文件無須特別配置,可以為每個app自定義日志收集配置
缺點:強耦合,不方便應用和日志收集組件升級和維護且會導致鏡像過大
- 單獨創建一個日志收集組件跟app的容器一起運行在同一個pod中
優點:低耦合,擴展性強,方便維護和升級
缺點:需要對kubernetes的yaml文件進行單獨配置,略顯繁瑣
- 將所有的Pod的日志都掛載到宿主機上,每台主機上單獨起一個日志收集Pod
優點:完全解耦,性能最高,管理起來最方便
缺點:需要統一日志收集規則,目錄和輸出方式
綜合以上優缺點,我們選擇使用方案二
架構圖如下:
我們在部署時,將Elasticsearch及kibana部署在k8s集群之外。
安裝Elasticsearch
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.4.tar.gz
tar -zxvf elasticsearch-6.2.4.tar.gz
vi config/elasticsearch.yml
#添加以下配置,或者將對應的配置注釋取消修改
network.host: 0.0.0.0
http.port: 9200
由於Elasticsearch不能使用root用戶打開,所以需要專門創建一個用戶來啟動Elasticsearch
$ adduser elastic
#設置密碼
$ passwd elastic
#需要輸入2次密碼
#授權
$ chmod -R 777 /usr/local/elasticsearch-6.2.4
#切換用戶
$ su elastic
#創建的用戶名為elastic,其中/usr/local/elasticsearch-6.2.4為解壓出來的Elasticsearch主目錄
#啟動Elasticsearch
./bin/elasticsearch
#如果遇到錯誤:max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536]
vi /etc/security/limits.conf
#如果有 * soft nofile 65535 * hard nofile 65535 則將65535修改為65536,如果沒有則在后面添加,注意此處的65535對應descriptors [65535]中的65535,修改后的值65536對應increase to at least [65536],所以當提示不一致時,需要根據具體的錯誤提示具體修改
#如果遇到錯誤: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
vi /etc/sysctl.conf
vm.max_map_count=262144
sysctl -p
#以上2個修改需要在root用戶權限修改,如果是使用xshell開兩個窗口的話修改完成之后一定要斷開重新登錄一下,啟動成功用執行命令
curl 127.0.0.1:9200
#會得到類似以下json
{
"name" : "dQIO4Ad",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "P8KtmO3vQdactRW1jX9JnQ",
"version" : {
"number" : "6.2.4",
"build_hash" : "ccec39f",
"build_date" : "2018-04-12T20:37:28.497551Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
安裝Kibana
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.2.4-linux-x86_64.tar.gz
tar -zxvf kibana-6.2.4-linux-x86_64.tar.gz
vi config/kibana.yml
#添加以下配置或者取消注釋並修改
elasticsearch.url: "http://localhost:9200"
server.host: "0.0.0.0"
kibana.index: ".kibana"
#其中elasticsearch.url為Elasticsearch的地址,server.host默認是localhost,如果只是本地訪問可以默認localhost,如果需要外網訪問,可以設置為0.0.0.0
啟動Kibana
./bin/kibana
打開瀏覽器進入http://127.0.0.1:5601,會出現如下頁面
使用Filebeat收集Kubernetes的應用日志並發送到es
#制作docker鏡像
#filebeat.yml
filebeat.prospectors:
- type: log
enabled: true
paths:
- /logs/*.log #這里為讀取日志目錄的路徑,應用程序也需要配置成相應的目錄
multiline:
pattern: ^[0-9]{4}
negate: true
match: after
timeout: 3s
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 3
setup.kibana:
host: "0.0.0.0:5601"
output.elasticsearch:
hosts: ["0.0.0.233:9200"]
#Dockerfile
FROM elastic/filebeat:6.2.4
COPY ./filebeat.yml /usr/share/filebeat/filebeat.yml
USER root
RUN chown root:filebeat /usr/share/filebeat/filebeat.yml
USER filebeat
#執行命令
docker build --rm -t littlewrong/filebeat:6.2.4 .
docker push littlewrong/filebeat:6.2.4
創建pod,以應用filebeat進行日志收集
#twbpm.yml
apiVersion: apps/v1
kind: Deployment # 定義Kubernetes資源的類型為Deployment
metadata:
name: tw.bpm # 定義資源的名稱
namespace: application
labels:
app: tw.bpm
spec: # 定義資源的狀態。
replicas: 2 # 定義我們想運行多少個Pod,在這里我們希望運行2個
selector:
matchLabels: # 定義該部署匹配哪些Pod
app: tw.bpm
minReadySeconds: 5 # 可選,指定Pod可以變成可用狀態的最小秒數,默認是0
strategy: # 指定更新版本時,部署使用的策略
type: RollingUpdate # 策略類型,使用RollingUpdate可以保證部署期間服務不間斷
rollingUpdate:
maxUnavailable: 1 # 部署時最大允許停止的Pod數量(與replicas相比)
maxSurge: 1 # 部署時最大允許創建的Pod數量(與replicas相比)
template: # 用來指定Pod的模板,與Pod的定義類似
metadata:
labels: # 根據模板創建的Pod會被貼上該標簽,與上面的matchLabels對應
app: tw.bpm
spec:
containers:
- name: web
image: littlewrong/tw.bpm:1.0.20
imagePullPolicy: Always # 默認是IfNotPresent,如果設置成Always,則每一次部署都會重新拉取容器映像(否則,如果本地存在指定的鏡像版本,就不會再去拉取)
ports:
- containerPort: 8000
volumeMounts:
- name: twbpmshare
mountPath: /share
- name: app-bpmlogs
mountPath: /logs
- name: filebeat
image: littlewrong/filebeat:6.2.4
volumeMounts:
- name: app-bpmlogs
mountPath: /logs
volumes:
- name: twbpmshare
flexVolume:
driver: "fstab/cifs"
fsType: "cifs"
secretRef:
name: "cifs-secret"
options:
networkPath: "//192.168.0.120/public"
mountOptions: "dir_mode=0755,file_mode=0644,noperm"
- name: app-bpmlogs
emptyDir: {}
最后進入kibana中查看日志
六、常見場景
6.1、自動打包發布鏡像
通過github的action可以實現代碼的自動編譯,打包,及發送到鏡像倉庫,流程如下圖所示:
流程文件如下,當上傳版本有tag為v開頭的,則自動編譯並上傳到鏡像倉庫,最后由k8s進行編排更新。
name: Docker
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
tags:
- v*
env:
# 設置 docker 鏡像名
IMAGE_NAME: tw.bpm
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# 構建鏡像,指定鏡像名
- name: Build image
run: docker build . --file Dockerfile --tag $IMAGE_NAME
# 登錄到 dockerhub,使用 GitHub secrets 傳入賬號密碼,密碼被加密存儲在 GitHub 服務器,添加方法見下圖。
- name: Log into registry
run: echo "${{ secrets.ACCESS_TOKEN }}" | docker login --username ${{ secrets.ACCESS_TOKEN_NAME }} --password-stdin
# 推送鏡像
- name: Push image
run: |
# 拼接鏡像 id,這個鏡像 id 就是在使用 docker 鏡像時 pull 后面的名字。
IMAGE_ID=${{ secrets.ACCESS_TOKEN_NAME }}/$IMAGE_NAME
# 將所有的大寫字母轉為小寫
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
# 從 GitHub.ref 中取出版本
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# 從 tag 名字中替換 v 字符
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# Use Docker `latest` tag convention
[ "$VERSION" == "master" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
# 設置鏡像 id 和版本號
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
# 進行 push
docker push $IMAGE_ID:$VERSION
Dockerfile如下:
# 拉去3.1的SDK作為打包環境
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS DOTNETCORE_BUILD
RUN apt-get update
RUN apt-get -y install libgdiplus
RUN apt-get -y install vim
RUN apt-get -y install net-tools
RUN apt-get -y install iputils-ping
RUN apt-get -y install telnet
RUN apt-get -y install procps
WORKDIR /build
# 將所有內容添加build目錄
COPY . /build
# 執行打包
RUN dotnet publish -c Release -o /build/publish
EXPOSE 8000
WORKDIR /build/publish/
ENTRYPOINT ["dotnet","RoadFlow.WebApi.dll"]
七、安裝與配置問題排查
7.1、docker常用命令
#進入容器
docker exec -ti 206b03a2d012 /bin/bash
1、刪除容器
1)首先需要停止所有的容器
docker stop $(docker ps -a -q)
2)刪除所有的容器(只刪除單個時把后面的變量改為image id即可)
docker rm $(docker ps -a -q)
2、刪除鏡像
1)查看host中的鏡像
docker images
2)刪除指定id的鏡像
docker rmi <image id>
想要刪除untagged images,也就是那些id為的image的話可以用
docker rmi $(docker images | grep "^" | awk "{print $3}")
3)刪除全部的images
docker rmi $(docker images -q)
3、當要刪除的iamges和其他的鏡像有關聯而無法刪除時
可通過 -f 參數強制刪除
docker rmi -f $(docker images -q)
#編輯docker容器中的文件
一般docker中沒有VI或者其它相應的文本編輯器,為了寫個東西安裝個vi就可以解決問題,除此之外還有別的辦法
登陸docker中找到需要編輯的文件的位置
sudo docker ps -a
sudo docker exec -it xxx /bin/bash
通過docker cp把這個文件拷貝出來
docker cp 1f6009256500:/etc/apt/sources.list /
再拷貝回去
docker cp /sources.list 1f6009256500:/etc/apt/sources.list
docker cp /daemon.json 1f6009256500:/etc/docker/daemon.json
apt-get install vim
打tag
docker tag bookingapi localhost:8888/bookingapi
推送
docker push localhost:8888/bookingapi
編譯運行:
docker build -t littlewrong/bpmapi .
docker run --name=bpmapi -p 8009:8000 -d littlewrong/bpmapi
鏡象搜索:
docker search Kubernetes-dashboard
docker iamges
docker ps -all-namespaces
7.2、kubernetes常用命令
查看錯誤:
kubectl describe pod istio-ingressgateway -n application
journalctl -f -u kubelet
kubectl logs tw.bpm-9588885ff --namespace=application
常用問題重啟:
systemctl restart kubelet
systemctl restart docker
kubectl get pods --all-namespaces
kubectl get services --all-namespaces
kubectl create -f kubernetes-dashboard.yaml
kubectl delete -f kubernetes-dashboard.yamlping
kubectl delete pod bookingapi-deployment-666979889-5b9lk -n
systemctl restart kube-apiserver
systemctl restart etcd
systemctl restart kube-apiserver
systemctl restart kube-controller-manager
systemctl restart kube-scheduler
systemctl restart kube-proxy
systemctl daemon-reload
systemctl restart docker.service
systemctl restart kubelet
systemctl restart docker
進入pod容器:
kubectl exec -it tw.charge-565fdd6c77-qq4d2 -n application -- /bin/bash
kubectl exec -ti tw.charge-565fdd6c77-qq4d2 -n application -- /bin/sh
docker exec -ti 26e371e71f45 /bin/bash
apt-get update
apt-get install vim
強制刪除pod:
kubectl delete pod bookingapi-5f96b5cbbb-29ghv -n default --grace-period=0 --force
kubectl delete -f your_file.yaml -n istio-system --grace-period=0 --force
查看錯誤:
journalctl -f -u kubelet.service
journalctl -f -u kubelet
kubectl describe pod bpmapi-5b6ff5dc4c-56dq4 -n application
kubectl logs bpmapi-5b6ff5dc4c-56dq4 --namespace=application
7.3、istio常用命令
#安裝指定插件
istioctl manifest apply --set addonComponents.egressGateways.enabled=true
istioctl manifest apply --set addonComponents.kiali.enabled=true
istioctl manifest apply --set values.pilot.traceSampling=0.1
istioctl install --set values.pilot.traceSampling=0.1
#打上注入標簽
kubectl label namespace default istio-injection=enabled
#刪除代理
kubectl label namespace default istio-injection-
istioctl kube-inject -f bookingapi-deployment.yaml | kubectl apply -f -
7.4、常見問題
發包后,讀取生產環境的appsetting.json失敗
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN apt-get update
RUN apt-get -y install libgdiplus
RUN apt-get -y install vim
RUN apt-get -y install net-tools
RUN apt-get -y install iputils-ping
RUN apt-get -y install telnet
RUN apt-get -y install procps
WORKDIR /app
COPY . .
EXPOSE 8000
ENTRYPOINT ["dotnet", "RoadFlow.WebApi.dll"]
#注意ENTRYPOINT的WORKDIR及當前目錄
pod內部無法ping通或者訪問外網或者外部服務
初始化kubernetes pod-network的IP千萬不要和局域網的IP重合,否則會造成pod內網不通外網的情況,一定切記切記
另外特別注意--pod-network-cidr的網段必須和kube-flannel的網段地址要保持一樣,否則也會造成pod內部IP不通的情況,最好設成默認的10.244.0.0/16
kubeadm init --kubernetes-version=v1.18.0 --service-cidr=10.1.0.0/16 --pod-network-cidr=10.10.0.0/16 --image-repository=registry.aliyuncs.com/google_containers --ignore-preflight-errors=all
kubernetes configmap目錄覆蓋
k8s在對目錄進行掛載后,其掛載的目錄里的所有文件會被覆蓋,需要指定 subPath 參數值。
.net core docker 鏡像差8個小時,時區問題,增加以下兩句話
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
.net core 的語言包本地化設置,默認情況下,dotnet並沒有任何語言包,在Dockerfile里增加以下兩句話
RUN apt-get -y install locales locales-all
ENV LANG zh_CN.UTF-8
八、結論
kubernetes+istio給我們提供了一個開箱即用的與開發語言無關的容器服務管理及治理平台,得益於強大的功能,使服務治理、運維及開發可以以一種較簡單協調的方式落地實施。
九、參考文檔
https://blog.csdn.net/hunyxv/article/details/92786490
https://blog.csdn.net/twingao/article/details/105382305
https://blog.csdn.net/codeex/article/details/86749817
https://istio.io/latest/zh/
https://kubernetes.io/zh/docs/home/
https://www.kubernetes.org.cn/2011.html
https://www.cnblogs.com/ajianboke/p/11275943.htmlwget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.4.tar.gz