# Introduction - Azure AKS Cilium EE Install Guide
This guide will help you to do a basic Cilium installation with some additional, advanced features:
- Cilium Enterprise
- KubeProxyReplacement (mode: `strict` or `true` if 1.14.x)
- IPv4-only
- Overlay routing with VXLAN-based encapsulation
- Hubble & Hubble Relay
- Cilium DNS Proxy HA
- Cilium Enterprise Dashboards
- Hubble UI Enterprise
In additional to the Cilium related tools, we'll install the following dependencies:
- Cert-Manager
- Grafana
- Kube-Prometheus-Stack
# Table of Content
[TOC]
# Prequisites
## General
- Ensure to have `kubectl` & `helm` CLI installed
- Deploy the AKS cluster with the no cni flag option --network-plugin none assuming you are using the az cli to build the AKS cluster
- Optional:
- Nginx ingress controller installed
- CSI plugin installed & `StorageClass` applied (used for Isovalent demo jobs-app)
## Pull Images / Charts
### Helm Chart Sources
```bash=
helm repo add isovalent https://helm.isovalent.com
helm repo add jetstack https://charts.jetstack.io
helm repo add grafana https://grafana.github.io/helm-charts
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
```
### Optional: Pull Helm Charts (Optional)
Only applicable if you're using a local repository. Skip this section if your cluster(s) can pull charts from the internet.
```bash=
helm pull isovalent/cilium --version 1.13.7
helm pull isovalent/cilium-dnsproxy --version 1.13.3
helm pull isovalent/hubble-ui --version 0.24.0
helm pull isovalent/hubble-enterprise --version 1.11.2
helm pull isovalent/jobs-app --version 0.8.0
helm pull jetstack/cert-manager --version v1.12.2
helm pull grafana/grafana --version 6.57.4
helm pull prometheus-community/kube-prometheus-stack --version 47.3.0
```
### Optional: Pull and Mirror Images (Optional)
Only applicable if you're using a local repository. Skip this section if your cluster(s) can pull images from the internet.
Helper script to extract image names (after running the provided `helm pull` commands from above):
```bash=
# Get `yq_darwin_arm64` from https://github.com/mikefarah/yq
for chart in $(ls *.tgz); do
echo $chart
helm template $chart | ./yq_darwin_arm64 -Nr '[.. | select(has("image")).image]' | sed -ne '/^- / s/^- "\(.*\)"$/\1/p' | sort -u
done
```
```bash=
# Define image array:
IMAGES=(
# cilium-dnsproxy
quay.io/isovalent/cilium-dnsproxy:v1.13.2
# Cilium
quay.io/isovalent/cilium:v1.13.4-cee.1
quay.io/cilium/certgen:v0.1.8@sha256:4a456552a5f192992a6edcec2febb1c54870d665173a33dc7d876129b199ddbd
quay.io/isovalent/hubble-relay:v1.13.4-cee.1
quay.io/cilium/cilium-etcd-operator:v2.0.7@sha256:04b8327f7f992693c2cb483b999041ed8f92efc8e14f2a5f3ab95574a65ea2dc
quay.io/isovalent/operator-generic:v1.13.4-cee.1
quay.io/cilium/startup-script:62093c5c233ea914bfa26a10ba41f8780d9b737f
quay.io/isovalent/clustermesh-apiserver:v1.13.4-cee.1
quay.io/coreos/etcd:v3.5.4@sha256:795d8660c48c439a7c3764c2330ed9222ab5db5bb524d8d0607cac76f7ba82a3
# Hubble-UI
cgr.dev/chainguard/oauth2-proxy:7.4.0@sha256:54857c70321004d3e0b8b8d7208ce5422c1f71c18db5be02d2543f187ea8e8e2
quay.io/isovalent/hubble-ui-enterprise-backend:v0.22.0
quay.io/isovalent/hubble-ui-enterprise:v0.22.0
# Hubble-Enterprise
quay.io/isovalent/hubble-enterprise:v1.10.5
quay.io/isovalent/hubble-enterprise-metadata:current
quay.io/isovalent/hubble-export-stdout:v1.0.3
quay.io/isovalent/hubble-export-fluentd:v1.5.1
quay.io/isovalent/hubble-export-s3:v1.0.0
# Isovalent Demos
# Jobs-App
quay.io/isovalent/jobs-app-coreapi:v0.8.0
quay.io/isovalent/jobs-app-crawler:v0.8.0
quay.io/isovalent/jobs-app-jobposting:v0.8.0
quay.io/isovalent/jobs-app-loader:v0.8.0
quay.io/isovalent/jobs-app-recruiter:v0.8.0
quay.io/isovalent/jobs-app-resumes:v0.8.0
# & 2 unknown Kafka Strimzi Operator images
# Star Wars
docker.io/cilium/starwars:latest
docker.io/tgraf/netperf:latest
# Cert-Manager
quay.io/jetstack/cert-manager-controller:v1.12.2
quay.io/jetstack/cert-manager-webhook:v1.12.2
quay.io/jetstack/cert-manager-cainjector:v1.12.2
quay.io/jetstack/cert-manager-acmesolver:v1.12.2
quay.io/jetstack/cert-manager-ctl:v1.12.2
# Grafana
docker.io/grafana/grafana:9.5.5
docker.io/bats/bats:v1.4.1
docker.io/curlimages/curl:7.85.0
docker.io/library/busybox:1.31.1
quay.io/kiwigrid/k8s-sidecar:1.24.3
docker.io/grafana/grafana-image-renderer:latest
quay.io/isovalent-dev/jwks-tools:latest
# Kube-Prometheus-Stack
registry.k8s.io/kube-state-metrics/kube-state-metrics:2.9.2
quay.io/brancz/kube-rbac-proxy:v0.14.0
quay.io/prometheus/node-exporter:v1.6.0
quay.io/prometheus/alertmanager:v0.25.0
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20221220-controller-v1.5.1-58-g787ea74b6
quay.io/prometheus-operator/prometheus-operator:v0.66.0
quay.io/prometheus-operator/prometheus-config-reloader:v0.66.0
quay.io/thanos/thanos:v0.31.0
quay.io/prometheus/prometheus:v2.45.0
)
# Pull all images:
for IMAGE in ${IMAGES[@]}; do
docker pull --platform x86_64 $IMAGE
# Something like this should to the trick to directly mirror the images to the custom registry:
#skopeo copy --multi-arch all docker://$IMAGE docker://harbor.example.com/project/$IMAGE
done
```
# Environment Validation
SSH to a worker node to validate some underlying infrastructure things:
```bash=
# Check SELinux status
sestatus
# Containerd & Kubelet Systemd service status
systemctl status kubelet
systemctl status containerd
# Software versions
cat /etc/os-release
uname -r
crictl info
rpm -qa | grep kube
# Show running containers/pods
crictl ps -a
# Check if `cgroup2` is present
grep cgroup /proc/filesystems
# Validate containerd cgroup2 configuration (source: https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd-systemd)
grep "SystemdCgroup" /etc/containerd/config.toml
```
# Installation
## Dependency CRDs
```bash=
# Install Cert-Manager CRDs
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.crds.yaml
# Install Prometheus CRDs
kubectl apply -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.66.0/stripped-down-crds.yaml
```
## Replace Kube-Proxy wth Cilium Kube-Proxy-Replacement (Optional)
Should you wish to consume Cilium Ingress or GatewayAPI and benefit from our eBPF dataplane then you will need to replace Kube-Proxy (based on IPTables) with our Kube-Proxy-Replacement (KPR) feature following the guide below.
https://docs.isovalent.com/operations-guide/features/disabling-kube-proxy-azure/index.html
After Kube-Proxy has been removed, restart the nodes.
## Cilium
Create `ca-certs.sh` helper script to generate `cilium-ca` cert that's used for Hubble/ClusterMesh internal certificates (**important**: Run this script on Linux!):
```bash=
#!/bin/bash
set -euo pipefail
# Script to generate Cluster Mesh Certificate Authority certificate and key shared in each cluster
#
# The base64 encoded certificates and keys are used in Helm values file for each Cluster.
#
# Requirements:
# * openssl
#
# Usage:
# ./ca-certs.sh up
#
# Cleanup:
# ./ca-certs.sh down
CILIUM_CA_NAME="cilium-ca"
CILIUM_CA_CRT_FILENAME="${CILIUM_CA_NAME}-crt.pem"
CILIUM_CA_KEY_FILENAME="${CILIUM_CA_NAME}-key.pem"
function down() {
# Delete the certificates and private keys.
rm -f "${CILIUM_CA_CRT_FILENAME}" "${CILIUM_CA_KEY_FILENAME}"
}
function info() {
echo "==> ${1}"
}
function up() {
# Generate a private key and a certificate for the certificate authority.
info "Creating a certificate authority..."
if [[ ! -f "${CILIUM_CA_KEY_FILENAME}" ]];
then
openssl genrsa -out "${CILIUM_CA_KEY_FILENAME}" 4096
fi
if [[ ! -f "${CILIUM_CA_CRT_FILENAME}" ]];
then
openssl req -x509 \
-days 3650 \
-key "${CILIUM_CA_KEY_FILENAME}" \
-new \
-nodes \
-out "${CILIUM_CA_CRT_FILENAME}" \
-sha256 \
-subj "/CN=${CILIUM_CA_NAME}"
fi
# Grab the certificates and private keys into environment variables.
BASE64_ENCODED_CA_CRT="$(openssl base64 -A < ${CILIUM_CA_CRT_FILENAME})"
BASE64_ENCODED_CA_KEY="$(openssl base64 -A < ${CILIUM_CA_KEY_FILENAME})"
}
function warn() {
echo "(!) ${1}"
}
case "${1:-""}" in
"down")
down
;;
"up")
up
;;
*)
warn "Please specify one of 'up' or 'down'."
exit 1
;;
esac
```
Generate `cilium-ca` cert:
```bash=
chmod +x ca-certs.sh
./ca-certs.sh up
```
Configure `cilium` CA issuer:
```bash=
kubectl -n kube-system create secret tls cilium-ca \
--dry-run=client \
--cert=cilium-ca-crt.pem \
--key=cilium-ca-key.pem \
-o yaml | \
kubectl apply --server-side=true --force-conflicts -f -
echo "
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: cilium
namespace: kube-system
spec:
ca:
secretName: cilium-ca
" | kubectl apply -f-
```
Create Cilium's Helm values file (`cilium-values.yaml`)
Remove the image.override: sections if you are pulling the images from the internet. Otherwise, include the images you have pulled down to your local repository.
```yaml=
# -- Generic Cilium Agent Configurations
# Enable/disable debug logging
debug:
enabled: false
# -- Configure verbosity levels for debug logging
# This option is used to enable debug messages for operations related to such
# sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is
# for enabling debug messages emitted per request, message and connection.
#
# Applicable values:
# - flow
# - kvstore
# - envoy
# - datapath
# - policy
verbose: ~
# inform Cilium this is an AKS BYOCNI cluster
aksbyocni:
enabled: true
# Enable Cilium Ingress for exposing services via the cloud NLBs)
ingress:
enabled: true
# Configure unique cluster name & ID (used for ClusterMesh in the future)
cluster:
name: ${CLUSTER_NAME}
id: ${CLUSTER_ID}
# Configure IPAM/PodCIDR
ipam:
mode: cluster-pool
operator:
clusterPoolIPv4PodCIDRList:
- ${POD_CIDR}
clusterPoolIPv4MaskSize: 24
# Disable IPv6 support if IPv6 isn't used by the customer
ipv6:
enabled: false
# Routing/encapsulation mode
tunnel: vxlan
# KubeProxyReplacement
kubeProxyReplacement: "strict or true, depending on 1.13 vs 1.14"
k8sServiceHost: ${EXTERNAL_KUBE_APISERVER_HOST}
k8sServicePort: ${EXTERNAL_KUBE_APISERVER_PORT}
# Optionally override the images:
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/cilium:v1.13.4-cee.1
#certgen:
# image:
# override: CUSTOM_REGISTRY/quay.io/cilium/certgen:v0.1.8@sha256:4a456552a5f192992a6edcec2febb1c54870d665173a33dc7d876129b199ddbd
#etcd:
# image:
# override: CUSTOM_REGISTRY/quay.io/cilium/cilium-etcd-operator:v2.0.7@sha256:04b8327f7f992693c2cb483b999041ed8f92efc8e14f2a5f3ab95574a65ea2dc
#nodeinit:
# image:
# override: CUSTOM_REGISTRY/quay.io/cilium/startup-script:62093c5c233ea914bfa26a10ba41f8780d9b737f
# -- Monitoring and Flow Visibility
# Enable Cilium Hubble to gain visibility
hubble:
enabled: true
metrics:
enableOpenMetrics: true
enabled:
# https://docs.cilium.io/en/stable/observability/metrics/#hubble-exported-metrics
# Remove `;query` from the `dns` line for production -> bad metrics cardinality
- dns:labelsContext=source_namespace,destination_namespace;query
- drop:labelsContext=source_namespace,destination_namespace
- tcp:labelsContext=source_namespace,destination_namespace
- port-distribution:labelsContext=source_namespace,destination_namespace
- icmp:labelsContext=source_namespace,destination_namespace;sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity
- flow:sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity;labelsContext=source_namespace,destination_namespace
- "httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction;sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity"
- "policy:sourceContext=app|workload-name|pod|reserved-identity;destinationContext=app|workload-name|pod|dns|reserved-identity;labelsContext=source_namespace,destination_namespace"
serviceMonitor:
enabled: true
dashboards:
enabled: true
namespace: hubble-ui
annotations:
grafana_folder: "Hubble"
tls:
enabled: true
auto:
enabled: true
method: certmanager
certManagerIssuerRef:
group: cert-manager.io
kind: Issuer
name: cilium
relay:
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-relay:v1.13.4-cee.1
enabled: true
tls:
server:
enabled: true
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Enable Cilium Operator metrics
operator:
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/operator-generic:v1.13.4-cee.1
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Operator Dashboards will be added with Cilium EE 1.14
# dashboards:
# enabled: true
# annotations:
# grafana_folder: "Cilium Operator"
# Enable Cilium Agent metrics
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Cilium Agent Dashboards will be added with Cilium EE 1.14
#dashboards:
# enabled: true
# annotations:
# grafana_folder: "Cilium Agent"
# -- Advanced Cilium Feature Configurations
# Enable Cilium agent's support for Cilium DNS Proxy HA
extraConfig:
external-dns-proxy: "true"
# Optional: Cilium ClusterMesh
# Probably activated at a later point in time
# clustermesh:
# useAPIServer: true
# config:
# enabled: true
# clusters:
# - name: peer-cluster-1
# ips:
# - <peer-cluster-1-clusterMesh-APIserver-lb-service-ip>
# port: 2379
# - name: peer-cluster-1
# ips:
# - <peer-cluster-2-clusterMesh-APIserver-lb-service-ip>
# port: 2379
# apiserver:
# image:
# override: CUSTOM_REGISTRY/quay.io/isovalent/clustermesh-apiserver:v1.13.4-cee.1
# etcd:
# image:
# override: CUSTOM_REGISTRY/quay.io/coreos/etcd:v3.5.4@sha256:795d8660c48c439a7c3764c2330ed9222ab5db5bb524d8d0607cac76f7ba82a3
# metrics:
# etcd:
# enabled: true
# serviceMonitor:
# enabled: true
# service:
# type: LoadBalancer
# annotations: {} # Add required AWS annotations
# tls:
# auto:
# enabled: true
# method: certmanager
# certManagerIssuerRef:
# group: cert-manager.io
# kind: Issuer # or ClusterIssuer
# name: <issuer-name-placeholder>
```
Install Cilium:
```bash=
helm upgrade -i cilium isovalent/cilium \
-n kube-system \
--version 1.13.7 (to be confirmed) \
-n kube-system \
-f cilium-values.yaml
```
Verification:
```bash=
kubectl get ds -n kube-system cilium
kubectl get pods -n kube-system -l k8s-app=cilium
```
Sources:
- https://docs.isovalent.com/operations-guide/installation/certificates.html#auto-generated-certificates-via-cert-manager
- https://docs.isovalent.com/operations-guide/installation/clean-install.html
## Cilium DNS Proxy HA (Optional)
Remove the cilium-dns-proxy-ha-values.yaml section if you are pulling the images from the internet. Otherwise, include the image configuration below.
Create Helm values file for Cilium DNS Proxy HA (`cilium-dns-proxy-ha-values.yaml`):
```yaml=
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/cilium-dnsproxy:v1.13.2
```
Install Cilium DNS Proxy HA:
```bash=
helm upgrade -i cilium-dnsproxy isovalent/cilium-dnsproxy \
--version 1.13.2 \
-n kube-system \
-f cilium-dns-proxy-ha-values.yaml
```
Verification:
```bash=
kubectl rollout status -n kube-system ds/cilium-dnsproxy --watch
```
Sources:
- https://docs.isovalent.com/operations-guide/features/networking/dnsproxy-ha/index.html
## Cert-Manager
Remove the cert-manager-values.yaml section if you are pulling the images from the internet. Otherwise, include the image configuration below.
Create Helm values file for Cert-Manager (`cert-manager-values.yaml`):
```yaml=
# Either work with the registry value or prepend the custom registry URL to the repository. Don't to both!
image:
#registry: CUSTOM_REGISTRY
repository: CUSTOM_REGISTRY/quay.io/jetstack/cert-manager-controller
webhook:
image:
#registry: CUSTOM_REGISTRY
repository: CUSTOM_REGISTRY/quay.io/jetstack/cert-manager-webhook
cainjector:
image:
#registry: CUSTOM_REGISTRY
repository: CUSTOM_REGISTRY/quay.io/jetstack/cert-manager-cainjector
acmesolver:
image:
#registry: CUSTOM_REGISTRY
repository: CUSTOM_REGISTRY/quay.io/jetstack/cert-manager-acmesolver
startupapicheck:
image:
#registry: CUSTOM_REGISTRY
repository: CUSTOM_REGISTRY/quay.io/jetstack/cert-manager-ctl
```
Install Cert-Manager:
```bash=
helm upgrade -i cert-manager jetstack/cert-manager \
--create-namespace \
--skip-crds \
-n cert-manager \
--version v1.12.2 \
-f cert-manager-values.yaml
```
Source:
- https://cert-manager.io/docs/installation/helm/
## Hubble-UI
Create `hubble-ui` Namespace and copy over `cilium-ca` secret:
```bash=
# Create the hubble-ui NS:
kubectl create namespace hubble-ui --dry-run=client -o yaml | kubectl apply -f -
# Import the used cilium-ca from kube-system to hubble-ui NS:
kubectl -n kube-system get secrets cilium-ca --template '{{ index .data "tls.crt" }}' | base64 --decode > cilium-ca.crt
kubectl -n hubble-ui create secret generic cilium-ca \
--save-config \
--dry-run=client \
--from-file=tls.crt=cilium-ca.crt \
-o yaml | \
kubectl apply -f -
# Create the JWKS for Hubble-UI's authentication on Grafana:
JWKS_DICRECTORY=jwks
if [[ ! -d "$JWKS_DICRECTORY" ]]
then
mkdir -p $JWKS_DICRECTORY
docker run -v $(pwd)/$JWKS_DICRECTORY:/usr/src/app/jwks quay.io/isovalent-dev/jwks-tools create hubble-ui.json
docker run -v $(pwd)/$JWKS_DICRECTORY:/usr/src/app/jwks quay.io/isovalent-dev/jwks-tools public hubble-ui.json > $JWKS_DICRECTORY/hubble-ui-public.json
fi
# Create CM/secrets to access Grafana:
kubectl create configmap -n monitoring hubble-ui-grafana-public-jwks \
--dry-run=client \
--from-file=jwks=./jwks/hubble-ui-public.json \
-o yaml | \
kubectl apply --server-side=true --force-conflicts -f -
export GRAFANA_AUTH_USER=hubble-viewer
kubectl create secret -n hubble-ui generic hubble-ui-grafana-secret \
--dry-run=client \
--from-literal=endpoint=http://grafana.monitoring.svc.cluster.local. \
--from-literal=auth_token="$(docker run -v $(pwd)/$JWKS_DICRECTORY:/usr/src/app/jwks quay.io/isovalent-dev/jwks-tools jwt hubble-ui.json $GRAFANA_AUTH_USER)" \
-o yaml | \
kubectl apply --server-side=true --force-conflicts -f -
```
Create Hubble-UI values file (`hubble-ui-values.yaml`):
Remove the image.override: sections if you are pulling the images from the internet. Otherwise, include the images you have pulled down to your local repository.
```yaml=
relay:
address: "hubble-relay.kube-system.svc.cluster.local."
tls:
enabled: true
ca:
source: secret
secret:
name: cilium-ca
key: tls.crt
ingress:
annotations: {}
enabled: true
host: hubble-ui.<DOMAIN-POINTING-TO-CLUSTER-INGRESS>
ingressClassName: cilium
tls:
enabled: true
secretName: "hubble-ui-tls"
v1: true
#oauth2:
# proxy:
# image:
# override: CUSTOM_REGISTRY/cgr.dev/chainguard/oauth2-proxy:7.4.0
backend:
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-ui-enterprise-backend:v0.22.0
frontend:
# -- Hubble-ui frontend image.
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-ui-enterprise:v0.22.0
grafana:
enabled: true
namespace: "hubble-ui"
prometheusDatasourseUid: "Prometheus"
```
Installation:
```bash=
helm upgrade -i hubble-ui isovalent/hubble-ui \
--version 0.24.0 \
--namespace hubble-ui \
--create-namespace \
--values hubble-ui-values.yaml
```
Verification:
```bash=
kubectl get pods -n hubble-ui
kubectl port-forward -n hubble-ui svc/hubble-ui 12000:80
# ... and access the UI via browser: http://localhost:12000/
```
Sources:
- https://docs.isovalent.com/operations-guide/features/hubble-ui/install.html
- https://docs.isovalent.com/operations-guide/monitoring/hubble-ui-grafana.html
## Hubble-Enterprise
Remove the image.override: sections if you are pulling the images from the internet. Otherwise, include the images you have pulled down to your local repository.
Used for Hubble flow event export to ElasticSearch.
Create values file for Hubble Enterprise (`hubble-enterprise-values.yaml`):
```yaml=
hostNetwork: false
enterprise:
enabled: false
# image:
# override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-enterprise:v1.10.5
# metadataImage:
# override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-enterprise-metadata:current
hubbleEnterpriseOperator:
enabled: false
export:
mode: "fluentd"
# stdout:
# image:
# override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-export-stdout:v1.0.3
filenames:
- hubble.log
extraEnv:
- name: ELASTICSEARCH_HOST
valueFrom:
secretKeyRef:
name: hubble-enterprise-elastic-credentials
key: host
- name: ELASTICSEARCH_PORT
valueFrom:
secretKeyRef:
name: hubble-enterprise-elastic-credentials
key: port
- name: ELASTICSEARCH_USER
valueFrom:
secretKeyRef:
name: hubble-enterprise-elastic-credentials
key: user
- name: ELASTICSEARCH_PASSWORD
valueFrom:
secretKeyRef:
name: hubble-enterprise-elastic-credentials
key: password
fluentd:
image:
override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-export-fluentd:v1.5.1
output: |-
@type elasticsearch
host "#{ENV['ELASTICSEARCH_HOST']}"
port "#{ENV['ELASTICSEARCH_PORT']}"
user "#{ENV['ELASTICSEARCH_USER']}"
password "#{ENV['ELASTICSEARCH_PASSWORD']}"
# Names indexes fluentd.hubble.log and fluentd.fgs.log
index_name "fluentd.${tag}"
scheme https
ssl_verify false
verify_es_version_at_startup false
validate_client_version false
default_elasticsearch_version 7
# s3:
# image:
# override: CUSTOM_REGISTRY/quay.io/isovalent/hubble-export-s3:v1.0.0
grafana:
dashboards:
enabled: true
```
Create secret containing the ElasticSearch credentials:
```bash=
kubectl -n kube-system create secret generic hubble-enterprise-elastic-credentials \
--from-literal host="<ES_HOST>" \
--from-literal port="<ES_PORT>" \
--from-literal user="<ES_USER>" \
--from-literal password="<ES_PASSWORD>"
```
Install Hubble-Enterprise:
```bash=
helm upgrade -i hubble-enterprise isovalent/hubble-enterprise \
-n kube-system \
--version 1.10.5 \
-f hubble-enterprise-values.yaml
```
Sources:
- https://docs.isovalent.com/operations-guide/features/tetragon-security/event-export/elastic.html
## Grafana
Remove the image.repository: sections if you are pulling the images from the internet. Otherwise, include the images you have pulled down to your local repository.
Create values file for Grafana (`grafana-values.yaml`):
```bash=
adminPassword: <generate-top-secret-pw>
sidecar:
image:
repository: CUSTOM_REGISTRY/quay.io/kiwigrid/k8s-sidecar
#imageRenderer:
# image:
# repository: CUSTOM_REGISTRY/docker.io/grafana/grafana-image-renderer
dashboards:
enabled: true
label: grafana_dashboard
labelValue: "1"
searchNamespace: ALL
folderAnnotation: grafana_folder
provider:
foldersFromFilesStructure: true
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local.:9090
access: proxy
isDefault: true
image:
repository: CUSTOM_REGISTRY/docker.io/grafana/grafana
testFramework:
image: CUSTOM_REGISTRY/docker.io/bats/bats
downloadDashboardsImage:
repository: CUSTOM_REGISTRY/docker.io/curlimages/curl
initChownData:
image:
repository: CUSTOM_REGISTRY/docker.io/library/busybox
persistence:
enabled: true
size: 2Gi
storageClassName: aws-efs
grafana.ini:
security:
allow_embedding: true
auth.jwt:
enabled: true
enable_login_token: true
url_login: true
username_claim: sub
header_name: X-Forwarded-Access-Token
auto_sign_up: false
jwk_set_file: /var/lib/grafana/jwks/hubble-ui-public.json
extraConfigmapMounts:
- name: hubble-ui-grafana-public-jwks
mountPath: /var/lib/grafana/jwks/hubble-ui-public.json
subPath: jwks
configMap: hubble-ui-grafana-public-jwks
readOnly: true
ingress:
enabled: true
ingressClassName: cilium
hosts:
- grafana.<DOMAIN-POINTING-TO-CLUSTER-INGRESS>
```
Install Grafana:
```bash=
helm upgrade -i grafana grafana/grafana \
--create-namespace \
-n monitoring \
--version 6.57.4 \
-f grafana-values.yaml
```
Sources:
- https://github.com/grafana/helm-charts
## Kube-Prometheus-Stack
Remove the global.imageRegistry: sections if you are pulling the images from the internet. Otherwise, include the images you have pulled down to your local repository.
Create kube-prometheus-stack values file (`prometheus-values.yaml`):
```yaml=
global:
imageRegistry: "harbor.example.com/project"
# Disable Grafana since we install it via official Grafana Labs Helm chart
grafana:
enabled: false
# Disable kube-proxy because we use Cilium KubeProxyReplacement
kubeProxy:
enabled: false
# The following components are disable because we didn't configure kubeadm to expose those metric endpoints to far:
kubeControllerManager:
enabled: false
kubeScheduler:
enabled: false
kubeEtcd:
enabled: false
# Override images:
nodeExporter:
enabled: true
#kubeRBACProxy:
# image:
# registry: CUSTOM_REGISTRY/quay.io
#prometheus-node-exporter:
# image:
# registry: CUSTOM_REGISTRY/quay.io
# repository: prometheus/node-exporter
kubeStateMetrics:
enabled: false
alertmanager:
ingress:
enabled: true
ingressClassName: cilium
hosts:
- alertmanager.<DOMAIN-POINTING-TO-CLUSTER-INGRESS>
paths:
- /
# alertmanagerSpec:
# image:
# registry: CUSTOM_REGISTRY/quay.io
# repository: prometheus/alertmanager
prometheus:
ingress:
enabled: true
ingressClassName: cilium
hosts:
- prometheus.<DOMAIN-POINTING-TO-CLUSTER-INGRESS>
paths:
- /
prometheusSpec:
# image:
# registry: CUSTOM_REGISTRY/quay.io
# repository: prometheus/prometheus
# We only deploy a single Prometheus. Therefore this one should watch for all CRs regardless of the CR annotations.
ruleSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
podMonitorSelectorNilUsesHelmValues: false
probeSelectorNilUsesHelmValues: false
scrapeConfigSelectorNilUsesHelmValues: false
#prometheusOperator:
# image:
# registry: CUSTOM_REGISTRY/quay.io
# repository: prometheus-operator/prometheus-operator
# prometheusConfigReloader:
# image:
# registry: CUSTOM_REGISTRY/quay.io
# repository: prometheus-operator/prometheus-config-reloader
#thanosImage:
# registry: CUSTOM_REGISTRY/quay.io
# admissionWebhooks:
# patch:
# image:
# registry: CUSTOM_REGISTRY/registry.k8s.io
# repository: ingress-nginx/kube-webhook-certgen
#thanosRuler:
# thanosRulerSpec:
# image:
# registry: CUSTOM_REGISTRY/quay.io
```
Install the Prometheus stack:
```bash=
helm upgrade -i kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--create-namespace \
--skip-crds \
-n monitoring \
--version 47.3.0 \
-f prometheus-values.yaml
```
Sources:
- https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack
## Cilium Enterprise Dashboards (Optional)
(Not required in case Hubble-UI's Grafana integration is activated.)
Install Cilium Enterprise dashboards for Grafana:
```bash=
helm upgrade -i cilium-ee-dashboards isovalent/cilium-ee-dashboards \
--version 0.1.2 \
-n monitoring \
--create-namespace
```
Sources:
- https://docs.isovalent.com/operations-guide/monitoring/cilium-ee-dashboards.html
## Demo
### Lightweight Star Wars Demo
Remove CUSTOM_REGISTRY/ if you are pulling your images from the internet. Otherwise update the manifest with your local repository path.
Create the Star Wars demo manifest (`star-wars-demo.yaml`):
```yaml=
# https://docs.cilium.io/en/stable/gettingstarted/demo/#getting-started-with-the-star-wars-demo
---
apiVersion: v1
kind: Namespace
metadata:
name: star-wars-demo
---
apiVersion: v1
kind: Service
metadata:
name: deathstar
namespace: star-wars-demo
labels:
app.kubernetes.io/name: deathstar
spec:
type: ClusterIP
ports:
- port: 80
selector:
org: empire
class: deathstar
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deathstar
namespace: star-wars-demo
labels:
app.kubernetes.io/name: deathstar
spec:
replicas: 2
selector:
matchLabels:
org: empire
class: deathstar
template:
metadata:
labels:
org: empire
class: deathstar
app.kubernetes.io/name: deathstar
spec:
containers:
- name: deathstar
image: CUSTOM_REGISTRY/docker.io/cilium/starwars
---
apiVersion: v1
kind: Pod
metadata:
name: tiefighter
namespace: star-wars-demo
labels:
org: empire
class: tiefighter
app.kubernetes.io/name: tiefighter
spec:
containers:
- name: spaceship
image: CUSTOM_REGISTRY/docker.io/cilium/json-mock
command: ["/bin/sh"]
args: ["-c", "while true; do curl -s -XPOST http://deathstar/v1/request-landing; curl -s https://disney.com; curl -s https://swapi.dev/api/starships; sleep 5; done"]
---
apiVersion: v1
kind: Pod
metadata:
name: xwing
namespace: star-wars-demo
labels:
app.kubernetes.io/name: xwing
org: alliance
class: xwing
spec:
containers:
- name: spaceship
image: CUSTOM_REGISTRY/docker.io/cilium/json-mock
command: ["/bin/sh"]
args: ["-c", "while true; do curl -s -XPOST http://deathstar/v1/request-landing; curl -s https://disney.com; curl -s https://swapi.dev/api/starships; sleep 5; done"]
```
Apply it:
```bash=
kubectl apply -f star-wars-demo.yaml
```
### Isovalent DNS Visibility CiliumClusterwideNetworkPolicy
Create the DNS visibility CCNP manifest (`ccnp-cluster-dns-visibility.yaml`):
```yaml=
---
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: cluster-dns-visibility
spec:
endpointSelector: {}
# matchExpressions:
# - key: k8s:io.kubernetes.pod.namespace
# operator: NotIn
# values:
# - kube-system
egress:
# Allow all egress traffic to not break stuff. Remove for zero trust approach on the cluster!
- toEntities:
- all
# Allow DNS to coredns and matchPattern to activate DNS visibility
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"
```
Apply it:
```bash=
kubectl apply -f ccnp-cluster-dns-visibility.yaml
```
Sources:
- https://docs.isovalent.com/quick-start/connectivity_visibility.html#enabling-dns-visibility
### Isovalent HTTP Visibility CiliumClusterwideNetworkPolicy
Create the DNS visibility CCNP manifest (`ccnp-cluster-http-visibility.yaml`):
```yaml=
---
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: cluster-http-visibility
spec:
endpointSelector: {}
# matchExpressions:
# - key: k8s:io.kubernetes.pod.namespace
# operator: NotIn
# values:
# - kube-system
ingress:
# Allow all ingress traffic to not break stuff. Remove for zero trust approach on the cluster!
- fromEntities:
- all
- toPorts:
- ports:
- port: "80"
protocol: "TCP"
- port: "8080"
protocol: "TCP"
- port: "9080"
protocol: "TCP"
- port: "50051"
protocol: "TCP"
- port: "9200"
protocol: "TCP"
rules:
http:
- {}
```
Apply it:
```bash=
kubectl apply -f ccnp-cluster-http-visibility.yaml
```
Sources:
- https://docs.isovalent.com/quick-start/connectivity_visibility.html#enabling-http-visibility
### Optional: Isoavalent Jobs-App
**Important:** The Isovalent Jobs-App Helm chart currently doesn't support to override the images.
Ensure to have a default `StorageClass` available:
```bash=
kubectl get sc
```
Install the Isovalent job-app:
```bash=
helm upgrade -i jobs-app isovalent/jobs-app \
--create-namespace \
-n jobs-app \
--set networkPolicy.enabled=false \
--version 0.8.0
```