openshift 4.3 Istio的搭建(istio 系列一)
openshift 4.3 Istio的搭建
本文檔覆蓋了官方文檔的Setup的所有章節
安裝Istio
本次安裝的Istio版本為1.5.2,環境為openshift 4.3
註:不建議使用openshift 1.11(即kubernetes 3.11)安裝istio,可能會出現如下兼容性問題,參見此issue
must only have "properties", "required" or "description" at the root if the status subresource is enabled
openshift安裝Istio
istio的安裝涉及到兩個文件:profile和manifest。前者用於控制組件的安裝和組件的參數,profile配置文件所在的目錄為install/kubernetes/operator/profiles
;後者為安裝所使用的yaml文件,如service,deployment等,會用到profile提供的參數,manifest配置文件所在的目錄為install/kubernetes/operator/charts
。因此可以通過兩種方式安裝istio,一種是通過profile進行安裝,istio默認使用這種方式,如:
$ istioctl manifest apply --set profile=default
第二種是通過導出的manifest進行安裝,如:
$ kubectl apply -f $HOME/generated-manifest.yaml
參考不同平台可以參考對應的SetUp。在openshift下面部署istio需要注意版本:
OpenShift 4.1 and above use
nftables
, which is incompatible with the Istioproxy-init
container. Make sure to use CNI instead.
首先創建istio-system
命名空間
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: istio-system
labels:
istio-injection: disabled
EOF
允許istio的serviceaccount使用UID為0的用戶,使用的命名空間為istio-system
$ oc adm policy add-scc-to-group anyuid system:serviceaccounts:istio-system
istio默認會注入一個名為istio-init
的initContainer
,用於將pod的網路流量導向istio的sidecar proxy,該initContainer
需要用到完整的NET_ADMIN
和NET_RAW
capabilities來配置網路,由此可能造成安全問題,使用istio CNI插件可以替換istio-init
,且無需提升kubernetes RBAC許可權,見下:
# with istio-cni
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
runAsGroup: 1337
runAsNonRoot: true
runAsUser: 1337
# without istio-cni
capabilities:
add:
- NET_ADMIN
- NET_RAW
drop:
- ALL
privileged: false
readOnlyRootFilesystem: false
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0
由於openshift 4.1以上版本不再使用iptables,轉而使用nftables,因此需要安裝istio CNI插件,否則在sidecar注入時會出現如下istio iptables-restore: unable to initialize table 'nat'
的錯誤,即無法執行iptables-resotre
命令。
執行如下命令安裝istio-cni並使用default類型的profile(見下)安裝istio,具體參數含義參見官方文檔。
cat <<'EOF' > cni-annotations.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
cni:
enabled: true
namespace: kube-system
values:
cni:
excludeNamespaces:
- istio-system
- kube-system
chained: false
cniBinDir: /var/lib/cni/bin
cniConfDir: /etc/cni/multus/net.d
cniConfFileName: istio-cni.conf
sidecarInjectorWebhook:
injectedAnnotations:
"k8s.v1.cni.cncf.io/networks": istio-cni
EOF
$ istioctl manifest apply -f cni-annotations.yaml
安裝結果如下:
# oc get pod
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-64f6f9d5c6-lwcp8 1/1 Running 0 41m
istiod-5bb879d86c-6ttml 1/1 Running 0 42m
prometheus-77b9c64b9c-r2pld 2/2 Running 0 41m
# oc get pod -nkube-system
NAME READY STATUS RESTARTS AGE
istio-cni-node-2xzl8 2/2 Running 0 41m
istio-cni-node-4nb6k 2/2 Running 0 41m
istio-cni-node-7j5ck 2/2 Running 0 41m
istio-cni-node-f9bnf 2/2 Running 0 41m
istio-cni-node-lp7v6 2/2 Running 0 41m
為ingress gateway暴露router:
$ oc -n istio-system expose svc/istio-ingressgateway --port=http2
至此istio的基本組件已經安裝完畢,可以使用如下方式導出本次安裝的profile
$ istioctl profile dump -f cni-annotations.yaml > generated-profile.yaml
使用如下命令導出安裝istio的manefest
的內容
$ istioctl manifest generate -f cni-annotations.yaml > generated-manifest.yaml
校驗安裝結果
$ istioctl verify-install -f generated-manifest.yaml
istio會使用UID為1337的用戶將sidecar注入到應用中,openshift默認不允許使用該用戶,執行如下命令進行授權。target-namespace
為應用所在的命名空間。
$ oc adm policy add-scc-to-group privileged system:serviceaccounts:<target-namespace>
$ oc adm policy add-scc-to-group anyuid system:serviceaccounts:<target-namespace>
當清理應用pod後,需要刪除添加的許可權
$ oc adm policy remove-scc-from-group privileged system:serviceaccounts:<target-namespace>
$ oc adm policy remove-scc-from-group anyuid system:serviceaccounts:<target-namespace>
openshift下使用multus
管理CNI,它需要在應用的命名空間中部署NetworkAttachmentDefinition
來使用istio-cni插件,使用如下命令創建NetworkAttachmentDefinition
,target-namespace
替換為實際應用所在的命名空間。
$ cat <<EOF | oc -n <target-namespace> create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: istio-cni
EOF
移除應用後,使用如下方式移除NetworkAttachmentDefinition
$ oc -n <target-namespace> delete network-attachment-definition istio-cni
更新istio配置
例如可以使用如下方式卸載已經安裝的第三方工具Prometheus,注意必須帶上文件cni-annotations.yaml
,否則會使用默認的profile重新配置istio,這樣會導致刪除istio-cni。如果組件的配置沒有改變,則不會重新該組件的pod
$ istioctl manifest apply -f cni-annotations.yaml --set addonComponents.prometheus.enabled=false
openshif卸載istio
$ istioctl manifest generate -f cni-annotations.yaml | kubectl delete -f -
標準安裝istio
istioctl
使用內置的charts生成manifest,這些charts位於目錄install/kubernetes/operator/charts
。
# ll
total 36
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 base
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 gateways
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-cni
drwxr-xr-x. 5 root root 4096 Apr 21 06:51 istio-control
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istiocoredns
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-operator
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-policy
drwxr-xr-x. 8 root root 4096 Apr 21 06:51 istio-telemetry
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 security
直接執行如下命令即可安裝官方默認配置的istio。
$ istioctl manifest apply --set profile=default
istio默認支援如下6種profile
# istioctl profile list
Istio configuration profiles:
empty
minimal
remote
separate
default
demo
安裝的組件的區別如下:
default | demo | minimal | remote | |
---|---|---|---|---|
Core components | ||||
istio-egressgateway |
X | |||
istio-ingressgateway |
X | X | ||
istio-pilot |
X | X | X | |
Addons | ||||
grafana |
X | |||
istio-tracing |
X | |||
kiali |
X | |||
prometheus |
X | X | X |
使用如下方式可以查看某個profile的配置資訊,profile類型helm的values.yaml,用於給部署用的yaml提供配置參數。每個組件包含兩部分內容:components下的組件以及組件的參數value
istio提倡適應 IstioOperator
API進行訂製化配置。
$ istioctl profile dump default
使用如下方式可以查看某個組件的配置:
$ istioctl profile dump --config-path components.pilot default
在安裝前可以使用如下方式導出需要安裝的所有yaml資訊 ,包括CRD,deployment,service等
$ istioctl manifest generate --set profile=default --set hub=docker-local.com/openshift4 > $HOME/generated-manifest.yaml
在進行確認或修改之後可以使用apply
命令執行安裝
$ kubectl apply -f $HOME/generated-manifest.yaml
使用如下方式校驗安裝結果
$ istioctl verify-install -f $HOME/generated-manifest.yaml
自定義配置:
-
使用
--set
選項進行設置,如下面用於設置profile中的global.controlPlaneSecurityEnabled
為true$ istioctl manifest apply --set values.global.controlPlaneSecurityEnabled=true
-
如果修改的參數比較多,可以使用yaml文件統一進行配置,實際使用
IstioOperator
API進行profile的修改$ istioctl manifest apply -f samples/operator/pilot-k8s.yaml
istio的核心組件定義在 IstioOperator
API的components下面:
Components |
---|
base |
pilot |
proxy |
sidecarInjector |
telemetry |
policy |
citadel |
nodeagent |
galley |
ingressGateways |
egressGateways |
cni |
第三方插件可以在IstioOperator
API的addonComponents下指定,如:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
addonComponents:
grafana:
enabled: true
每個組件都有一個KubernetesResourceSpec
,用於設置如下k8s屬性
- Resources
- Readiness probes
- Replica count
- HorizontalPodAutoscaler
- PodDisruptionBudget
- Pod annotations
- Service annotations
- ImagePullPolicy
- Priority class name
- Node selector
- Affinity and anti-affinity
- Service
- Toleration
- Strategy
- Env
標準卸載istio
$ istioctl manifest generate <your original installation options> | kubectl delete -f -
更新Istio
升級過程中可能會造成流量中斷,為了最小化影響,需要確保istio中的各個組件(除Citadel)至少有兩個副本正在運行,此外需要通過PodDistruptionBudgets保證至少有一個可用的pod
-
首先下載最新的istio
-
校驗當前環境中支援的升級到的版本,如下命令會給出推薦的版本
$ istioctl manifest versions
-
確認需要升級的cluster是否正確
$ kubectl config view
-
通過如下命令執行升級,
<your-custom-configuration-file>
為當前版本的 IstioOperator API 配置 文件$ istioctl upgrade -f `<your-custom-configuration-file>`
istioctl upgrade不支援
--set
命令 -
在更新完畢之後,需要手動重啟帶有istio sidecar的pod來更新istio數據面
$ kubectl rollout restart deployment
sidecar注入
為了使用Istio的特性,pods必須運行在istio sidecar proxy的網格中。下面介紹兩種注入istio sidecar的方式:手動注入和自動注入。
手動注入通過直接修改,如deployment的配置資訊,將proxy配置注入到配置中;當應用所在的命名空間啟用自動注入時,會在pod創建時通過mutating webhook admission controller 注入proxy配置。
sidecar(手動或自動)注入會用到istio-sidecar-injector
configmap。
-
手動注入
當前版本手動注入時有一個問題,就是使用istio CNI之後無法將annotation
k8s.v1.cni.cncf.io/networks
注入(或導出)到配置文件中,導致出現如下問題,參見該issue:in new validator: 10.80.2.222 Listening on 127.0.0.1:15001 Listening on 127.0.0.1:15006 Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
手動注入需要滿足一個條件,即在應用所在的命名空間中創建NetworkAttachmentDefinition
-
一種是直接使用
istio-sidecar-injector
的默認配置直接注入sidecar$ istioctl kube-inject -f samples/sleep/sleep.yaml | kubectl apply -f -
可以使用如下方式直接導出注入sidecar的deployment,並使用kubectl直接部署
$ istioctl kube-inject -f samples/sleep/sleep.yaml -o sleep-injected.yaml --injectConfigMapName istio-sidecar-injector $ kubectl apply -f deployment-injected.yaml
-
另一種是先導出
istio-sidecar-injector
的默認配置,可以修改後再手動注入sidecar導出配置:
$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml $ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.values}' > inject-values.yaml $ kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml
手動注入:
$ istioctl kube-inject \ --injectConfigFile inject-config.yaml \ --meshConfigFile mesh-config.yaml \ --valuesFile inject-values.yaml \ --filename samples/sleep/sleep.yaml \ | kubectl apply -f -
-
-
自動注入
自動注入時需要滿足兩個條件:
-
給應用所在的命名空間打上標籤
istio-injection=enabled
$ kubectl label namespace <app-namespace> istio-injection=enabled
-
與手動注入相同,需要在應用所在的命名空間中創建NetworkAttachmentDefinition
然後在該命名空間下面正常創建(或刪除並重建)pod即可自動注入sidecar。需要注意的是自動注入發生在pod層,並不體現在deployment上面,可以使用
describe pod
查看注入的sidecar。自動注入通過mutatingwebhookconfiguration定義了注入的命名空間的規則,當前是istio-injection=enabled label
namespaceSelector: matchLabels: istio-injection: enabled
可以通過如下命令修改注入的·規則,修改後需要重啟已經注入sidecar的pod,使規則生效
$ kubectl edit mutatingwebhookconfiguration istio-sidecar-injector
自動注入下,sidecar inject的webhook默認是打開的,如果要禁用該webhook,可以在上面cni-annotations.yaml文件中將
sidecarInjectorWebhook.enabled
置為false
,這樣就不會自動注入。
-
sidecar的注入控制
有兩種方式可以控制sidecar的注入:
-
第一種是修改pod template spec的
sidecar.istio.io/inject
annotation:當該annotation為true
時會進行自動注入sidecar,為false
則不會注入sidecar。默認為true
。這種情況需要修改應用的deploymentapiVersion: apps/v1 kind: Deployment metadata: name: ignored spec: template: metadata: annotations: sidecar.istio.io/inject: "false" spec: containers: - name: ignored image: tutum/curl command: ["/bin/sleep","infinity"]
-
第二種是修改
istio-sidecar-injector
configmap,通過在neverInjectSelector
數組中羅列出標籤,並禁止對匹配標籤的pod注入sidecar(各個匹配項的關係為OR
)。如下內容中不會對擁有標籤openshift.io/build.name
或openshift.io/deployer-pod-for.name
的pod注入sidecar。這種方式不需要修改應用的deployment。類似地,可以使用alwaysInjectSelector
來總是對某些具有特殊標籤的pod注入sidecarapiVersion: v1 kind: ConfigMap metadata: name: istio-sidecar-injector data: config: |- policy: enabled neverInjectSelector: - matchExpressions: - {key: openshift.io/build.name, operator: Exists} - matchExpressions: - {key: openshift.io/deployer-pod-for.name, operator: Exists} template: |- initContainers: ...
更多istio CNI與sidecar注入和流量重定向相關的參數參見官方文檔
卸載自動注入
使用如下方式可以卸載自動注入功能:
$ kubectl delete mutatingwebhookconfiguration istio-sidecar-injector
$ kubectl -n istio-system delete service istio-sidecar-injector
$ kubectl -n istio-system delete deployment istio-sidecar-injector
$ kubectl -n istio-system delete serviceaccount istio-sidecar-injector-service-account
$ kubectl delete clusterrole istio-sidecar-injector-istio-system
$ kubectl delete clusterrolebinding istio-sidecar-injector-admin-role-binding-istio-system
注意上面命令並不會卸載已經注入到pod的sidecar,需要通過滾動更新或直接刪除pod來生效
或者使用如下方式對某個命名空間禁用自動注入:
$ kubectl label namespace <target-namespace> istio-injection-
Istio CNI的兼容
與init容器的兼容
當使用istio CNI的時候,kubelet會按照如下步驟啟動注入sidecar的pod:
- 使用istio CNI插件進行配置,將流量導入到pod中的istio sidecar proxy容器
- 執行所有init容器,並成功運行結束
- 啟動pod中的istio sidecar proxy和其他容器
由於init容器會在sidecar proxy容器之前運行,因此可能導致應用本身的init容器通訊中斷。為了避免發生這種情況,可以使用如下配置避免重定嚮應用的init容器的流量:
- 設置
traffic.sidecar.istio.io/excludeOutboundIPRanges
annotation來禁止將流量重定向到init容器通訊的CIDRs - 設置
traffic.sidecar.istio.io/
excludeOutboundPorts` annotation來禁止將流量重定向到init容器使用的出站埠
與其他CNI插件的兼容
istio CNI插件作為CNI插件鏈中的一環,當創建或刪除一個pod時,會按照順序啟動插件鏈上的每個插件,istio CNI插件僅僅(通過pod的網路命名空間中的iptables)將應用的pod流量重定向到注入的istio proxy sidecar容器。
istio CNI插件不會幹涉配置pod網路的基本CNI插件。
更多細節參見CNI specification reference
TIPs:
-
不同平台下使用istio CNI執行initContainer時可能會出現istio-validation無法啟動的錯誤,這種情況下默認會導致kubelet刪除並重建pod,為了定位問題,可以將
repair.deletePods
配置為false,這樣就不會立即刪除podapiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: components: cni: ... values: cni: repair: enabled: true deletePods: false ...