kubernetes 1.9+node
首選須要建立一個apiservice(custom metrics AP)。nginx
adapter會根據配置的rules從Prometheus抓取並處理metrics,在處理(如重命名metrics等)完後將其發送到kubernetes的custom metrics API。後續HPA會經過該custom metrics API獲取metrics的value進行擴縮容git
部署adapter前須要配置adapter的rule,默認配置爲manifests/custom-metrics-config-map.yaml
。adapter的配置主要分爲4個:github
Discovery:指定如何獲取Prometheus的metrics數據,經過seriesQuery挑選須要處理的metrics集合,能夠經過seriesFilters精確過濾metrics。正則表達式
seriesQuery能夠根據標籤進行查找(以下),也能夠直接指定metric name查找shell
seriesQuery: '{__name__=~"^container_.*_total",container_name!="POD",namespace!="",pod_name!=""}' seriesFilters: - isNot: "^container_.*_seconds_total"
seriesFilters:json
is: <regex>, 匹配包含該正則表達式的metrics. isNot: <regex>, 匹配不包含該正則表達式的metrics.
Association:設置metric與kubernetes resources的映射關係,kubernetes resorces能夠經過kubectl api-resources
命令查看。overrides會將Prometheus label與一個kubernetes resource(下例爲deployment)關聯。須要注意的是該label必須是一個真實的kubernetes resource,如metric的pod_name能夠映射爲kubernetes的pod resource,但不能將container_image映射爲kubernetes的pod resource,映射錯誤可能會致使沒法經過custom metrics API獲取正確的值。這也表示metric中必須存在一個真實的resource 名稱,將其轉化爲kubernetes resource。bootstrap
resources: overrides: microservice: {group: "apps", resource: "deployment"}
Naming:用於將prometheus metrics名稱轉化爲custom metrics API所使用的metrics名稱。若是不須要能夠不執行這一步。api
# match turn any name <name>_total to <name>_per_second # e.g. http_requests_total becomes http_requests_per_second name: matches: "^(.*)_total$" as: "${1}_per_second"
如本例中HPA後續能夠經過/apis/{APIService-name}/v1beta1/namespaces/{namespaces-name}/pods/*/http_requests_per_second
獲取metricsbash
Querying:處理調用custom metrics API獲取到的metrics的value
# convert cumulative cAdvisor metrics into rates calculated over 2 minutes metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[2m])) by (<<.GroupBy>>)"
metricsQuery
字段使用Go template將URL請求轉變爲Prometheus的請求,它會提取custom metrics APIq請求中的字段,並將其劃分爲metric name,group-resource,以及group-resource中的一個或多個objects,對應以下字段:
Series
: metric名稱LabelMatchers
: 以逗號分割的objects,當前表示特定group-resource加上命名空間的label(若是該group-resource 是namespaced的)GroupBy
:以逗號分割的label的集合,當前表示LabelMatchers中的group-resource label假設metrics http_requests_per_second
以下
http_requests_per_second{pod="pod1",service="nginx1",namespace="somens"} http_requests_per_second{pod="pod2",service="nginx2",namespace="somens"}
當調用kubectl get --raw "/apis/{APIService-name}/v1beta1/namespaces/somens/pods/*/http_request_per_second"
時,metricsQuery
字段的模板的實際內容以下:
Series: "http_requests_total"
LabelMatchers: "pod=~\"pod1|pod2",namespace="somens"
GroupBy:pod
github下載k8s-prometheus-adapter
參照官方文檔部署
pull鏡像:directxman12/k8s-prometheus-adapter:latest,修改鏡像tag並push到本地鏡像倉庫
運行gencerts.sh生成cm-adapter-serving-certs.yaml,並將其拷貝到manifests/
目錄下
#!/usr/bin/env bash # exit immediately when a command fails set -e # only exit with zero if all commands of the pipeline exit successfully set -o pipefail # error on unset variables set -u # Detect if we are on mac or should use GNU base64 options case $(uname) in Darwin) b64_opts='-b=0' ;; *) b64_opts='--wrap=0' esac go get -v -u github.com/cloudflare/cfssl/cmd/... export PURPOSE=metrics openssl req -x509 -sha256 -new -nodes -days 365 -newkey rsa:2048 -keyout ${PURPOSE}-ca.key -out ${PURPOSE}-ca.crt -subj "/CN=ca" echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","'${PURPOSE}'"]}}}' > "${PURPOSE}-ca-config.json" export SERVICE_NAME=custom-metrics-apiserver export ALT_NAMES='"custom-metrics-apiserver.monitoring","custom-metrics-apiserver.monitoring.svc"' echo "{\"CN\":\"${SERVICE_NAME}\", \"hosts\": [${ALT_NAMES}], \"key\": {\"algo\": \"rsa\",\"size\": 2048}}" | \ cfssl gencert -ca=metrics-ca.crt -ca-key=metrics-ca.key -config=metrics-ca-config.json - | cfssljson -bare apiserver cat <<-EOF > cm-adapter-serving-certs.yaml apiVersion: v1 kind: Secret metadata: name: cm-adapter-serving-certs data: serving.crt: $(base64 ${b64_opts} < apiserver.pem) serving.key: $(base64 ${b64_opts} < apiserver-key.pem) EOF
建立命名空間:kubectl create namespace custom-metrics
openshift的kube-system下面可能沒有role extension-apiserver-authentication-reader
,若是不存在,則須要建立
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults name: extension-apiserver-authentication-reader namespace: kube-system rules: - apiGroups: - "" resourceNames: - extension-apiserver-authentication resources: - configmaps verbs: - get
修改custom-metrics-apiserver-deployment.yaml的--prometheus-url
字段,指向正確的prometheus
建立其餘組件:kubectl create -f manifests/
,
HPA支持的metrics類型有4種(下述爲v2beta2的格式):
resource:目前僅支持cpu
和memory
。target能夠指定數值(targetAverageValue
)和比例(targetAverageUtilization
)進行擴縮容
pods:custom metrics,這類metrics描述了pod,target僅支持按指定數值(targetAverageValue
)進行擴縮容。targetAverageValue
用於計算全部相關pods上的metrics的平均值
type: Pods pods: metric: name: packets-per-second target: type: AverageValue averageValue: 1k
object:custom metrics,這類metrics描述了相同命名空間下的(非pod)對象。target支持經過value
和AverageValue
進行擴縮容,前者直接將metric與target比較進行擴縮容,後者經過metric/相關的pod數目
與target比較進行擴縮容
type: Object object: metric: name: requests-per-second describedObject: apiVersion: extensions/v1beta1 kind: Ingress name: main-route target: type: Value value: 2k
external:kubernetes 1.10+。這類metrics與kubernetes集羣無關。與object相似,target支持經過value
和AverageValue
進行擴縮容。因爲external能夠嘗試匹配全部metrics,所以實際中不建議使用該類型。
- type: External external: metric: name: queue_messages_ready selector: "queue=worker_tasks" target: type: AverageValue averageValue: 30
1.6版本支持多metrics的擴縮容,當其中一個metrics達到擴容標準時就會建立pod副本(當前副本<maxReplicas)
注:target的value的一個單位能夠劃分爲1000份,每一份以m
爲單位,如500m表示1/2
個單位。參見Quantity
假設註冊的APIService爲custom.metrics.k8s.io/v1beta1,在註冊好APIService後HorizontalPodAutoscaler controller會從以/apis/custom.metrics.k8s.io/v1beta1
爲根API的路徑上抓取metrics。metrics的API path能夠分爲namespaced
和non-namespaced
類型的。經過以下方式校驗HPA是否能夠獲取到metrics:
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/{object-type}/{object-name}/{metric-name...}"
如獲取monitor
命名空間下名爲grafana
的pod的start_time_seconds
metric
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitor/pods/grafana/start_time_seconds"
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/pods/*/{metric-name...}"
如獲取monitor
命名空間下名爲全部pod的start_time_seconds
metric
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitor/pods/*/start_time_seconds"
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/{object-type}/{object-name}/{metric-name...}?labelSelector={label-name}"
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/pods/*/{metric-name...}?labelSelector={label-name}"
non-namespaced和namespaced的相似,主要有node,namespace,PersistentVolume等。non-namespaced訪問有些與custom metrics API描述不一致。
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/metrics/{metric-name...}"
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/*/metrics/{metric-name...}"
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/nodes/{node-name}/{metric-name...}"
使用以下方式查看註冊的APIService發現的全部rules
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
若是獲取失敗,能夠看下使用oc get apiservice v1beta1.custom.metrics.k8s.io -oyaml
查看status
和message
的相關信息
經過以下方式查看完整的請求過程(--v=8)
kubectl get --raw 「/apis/custom.metrics.k8s.io/v1beta1/namespaces/{namespace-name}/pods/*/{metric-name...}" --v=8
--metrics-relist-interval
設置值大於Prometheus的參數scrape_interval
rules
的seriesQuery
規則能夠抓取到Prometheus的數據rules
的metricsQuery
規則能夠抓取到計算出數據,此處須要注意的是,若是使用到了計算某段時間的數據,若是時間設置太短,可能致使沒有數據生成pod
和`namespace label,不然在官方默認配置下沒法採集到metrics。遺留問題:
HPA是如何感知註冊的apiservice的?
apiservice的工做模型