Skip to content

Commit

Permalink
Extend connectivity-check for HTTP policy validation via CUE (#12599)
Browse files Browse the repository at this point in the history
* connectivity-check: Add 'make clean' support

Factor out the targets for all YAMLs so it can be reused by a new phony
target, 'clean'.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Introduce cuelang framework

CUE (https://cuelang.org/) is a data constraint language built defined
as a superset of JSON which aims to "simplify tasks involving defining
and using data".

In context of the connectivity check YAMLs, CUE is useful to allow us to
"evaporate" the boilerplate necessary to define Kubernetes YAMLs for
Deployments, Services and CiliumNetworkPolicies and allow developers to
specify various permutations for connectivity checks concisely.

Why should we use it?

* It's more concise: One template definition, multiple reuse. This is
  useful for introducing new connectivity checks as upcoming commits
  will demonstrate as the developer doesn't need to perform the tedious
  and error-prone process of copying and modifying the YAMLs to
  implement various permutations of a check. Furthermore this helps
  reviewers as they will not have to read through swathes of YAMLs but
  can instead focus on the diffs in the templating that are introduced
  and compare to existing data definitions.

* Consolidate constant declaration. When a core change needs to be made
  to something like the readinessProbe for probes that expect a
  success or failure, we can update one definition in the main CUE file
  and all YAMLs will subsequently be generated with this change in mind.
  During the process of preparing these changes, I noticed
  inconsistencies between various existing YAMLs which appear to just be
  unintentional, where some YAMLs were improved with better timeoute
  behaviour or error rendering, but other YAMLs were left out.

* The data is more structured. Upcoming commits will introduce simple
  CLI tools that allow matching on different classes of connectivity
  checks to generate the corresponding YAMLs. Previously we have
  depended upon file naming schemes and Makefile globbing magic to
  implement this which quickly reaches a limit in which checks should be
  selected for a specific check.

What are the dangers?

* It's relatively immature. At current version v0.2.2 it is subject to
  language changes. Upcoming commits will pin the CLI tool usage to a
  docker container derived from this version to ensure compatibility.
* One more language in the tree to understand, review and interact with.
  Mitigating circumstances: This language comes out of the Golang
  community and as such brings some commonalities; furthermore it is
  beginning to be used in other Kubernetes projects, so there is some
  broader community alignment.
* Its power allows you to hide as much or as little complexity as you
  want. It's tricky to strike a fine balance between explicitly declaring
  (and duplicating) relevant fields in the local file vs. hiding
  convenient templating language in common files. For examples, see
  defaults.cue which automatically derives connectivity check destinations
  based on object name declarations matching regexes of "pod-to-X", and
  applies affinity/anti-affinity via matches on "intra-host" or
  "multi-host".
* All declarations are additive, ie there is no ordering based upon the
  layout in code; instead, data dependencies are determined using the
  declarations, and all data is arranged into a lattice to determine the
  evaluation ordering[0]. This can be counter-intuitive to reason about
  for the uninitiated.

The general approach used in this commit was to `cue import` various
existing YAML files to generate JSON equivalents, then iteratively
combining & consolidating existing definitions using the language
constructs provided by CUE. CUE also provides mechanisms to generate
schemas and autogenerate the structures used here directly from API
definitions (eg from k8s source or Cilium tree), however this area was
not explored in this PR yet. While this doesn't take advantage of one
major aspect of the language, upcoming commits will demonstrate the way
that these changes were validated without the use of standardized
schemas from the underlying Kubernetes resource definitions. (TL;DR:
`kubectl diff ...` with kubectl validation on a live cluster). This was
sufficient to extend the connectivity checks and does not preclude
future explanation of the use of schemas for these definitions.

This commit introduces usage of CUE in a relatively minimal way into the
tree which was useful for my goals of extending the connectivity checks.
If we find that it is useful and powerful, we may consider whether to
extend its usage to other areas of the code (such as for test manifest
generation).

[0] https://cuelang.org/docs/concepts/logic/#the-value-lattice

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Add cue CLI tools

Add some basic tooling around connectivity-check YAML generation:

  $ cue cmd help
  List connectivity-check resources specified in this directory

  Usage:
    cue [-t component=<component>] [-t name=<name>] [-t topology=<topology>] <command>

  Available Commands:
    dump   Generate connectivity-check YAMLs from the cuelang scripts
    ls     List connectivity-check resources specified in this directory

List available connectivity-check components:

  $ cue cmd ls
  KIND                  COMPONENT        TOPOLOGY     NAME
  Service               network-check    any          echo-a
  Service               services-check   any          echo-b
  Service               services-check   any          echo-b-headless
  Service               services-check   any          echo-b-host-headless
  Deployment            network-check    any          echo-a
  Deployment            services-check   any          echo-b
  Deployment            services-check   any          echo-b-host
  Deployment            network-check    any          pod-to-a
  Deployment            network-check    any          pod-to-external-1111
  Deployment            policy-check     any          pod-to-a-allowed-cnp
  Deployment            policy-check     any          pod-to-a-denied-cnp
  Deployment            policy-check     any          pod-to-external-fqdn-allow-google-cnp
  Deployment            services-check   multi-node   pod-to-b-multi-node-clusterip
  Deployment            services-check   multi-node   pod-to-b-multi-node-headless
  Deployment            services-check   intra-node   pod-to-b-intra-node-clusterip
  Deployment            services-check   intra-node   pod-to-b-intra-node-headless
  Deployment            services-check   multi-node   host-to-b-multi-node-clusterip
  Deployment            services-check   multi-node   host-to-b-multi-node-headless
  CiliumNetworkPolicy   policy-check     any          pod-to-a-allowed-cnp
  CiliumNetworkPolicy   policy-check     any          pod-to-a-denied-cnp
  CiliumNetworkPolicy   policy-check     any          pod-to-external-fqdn-allow-google-cnp

These can be filtered by component, topology or name. For example:

  $ cue cmd -t component=network ls
  KIND         COMPONENT       TOPOLOGY    NAME
  Service      network-check   any         echo-a
  Deployment   network-check   any         echo-a
  Deployment   network-check   any         pod-to-a
  Deployment   network-check   any         pod-to-external-1111

Finally, to gather the (filtered) YAMLs for the specified resources:

  $ cue cmd dump | head -n 20
  metadata:
    name: echo-a
    labels:
      name: echo-a
      topology: any
      component: network-check
  spec:
    ports:
      - port: 80
    selector:
      name: echo-a
    type: ClusterIP
  apiVersion: v1
  kind: Service
  ---
  ...

Or with an upcoming commit you can just use the Makefile, which now depends
on the cuelang/cue:v0.2.2 Docker image:

  $ make connectivity-check.yaml

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Support generating YAMLs via cue

Replace the existing YAML generation from individual YAML declarations
for each service with generating YAMLs from the CUE definitions.

Three new targets will assist in validating the migration from the
existing definitions over to CUE:

 * make generate_all
   * For object declared in CUE, generate a file corresponding to that
     definition. For most of the existing YAMLs, this will overwrite the
     copy of the YAML in the tree. This can allow manual inspection of
     individual YAMLs, though the 'inspect' approach is broadly more
     useful for evaluating the overall diff.
 * make deploy
   * Deploy the hostport connectivity checks YAML into an existing cluster.
 * make inspect
   * Generate the YAML file for all connectivity checks, then use
     kubectl to diff these newly generated definitions against the
     running cluster (assuming it was deployed via make deploy).

This commit is purely the makefile changes for easier review &
inspection. Upcoming commits will use these targets to demonstrate that
there is no meaningful change in the generated YAMLs for existing YAMLs
in the tree. In particular, `make inspect` can be used in an iterative
manner by initially deploying the current version of the YAMLs from the
tree, then making changes to the CUE files and inspecting each time a
change is made. When the diff in the cluster represents the changes that
the developer intends to make, the developer can commit the changes to
the CUE files and re-generate the tree versions of the YAMLs.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Replace YAMLs with cue-generated YAMLs

Prior commits introduced CUE definitions that are equivalent to these
YAML files, so we can now:

 * Remove the individual declarations which were previously
   source-of-truth for the connectivity checks
 * Update the overall connectivity-check YAMLs to reflect the minor
   changes that the CUE definitions represent.

To validate this, heavy use of `make inspect` was used. As described in
the prior commit message where this was introduced, this allows diffing
the latest CUE-based YAML definitions against a running copy of the
YAMLs in a cluster.

There are few meaningful changes in this commit which are hard to assess
directly from the git diff, but are easier using `make inspect`:

 * All containers are converted to use readinessProbe and not
   livenessProbe.
 * All readiness probes now specify --connect-timeout of 5s.
 * Readiness probes access `/public` or `/private` per the underlying
   container HTTP server paths rather than just accessing `/`.
 * DNS allow policies are converted to consistently allow both TCP and
   UDP-based DNS.
 * Container names are derived from pod names.
 * The new YAMLs declare additional labels for all resourcess, such as
   'component' and 'topology'.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Introduce proxy checks

These new checks configure various L7 proxy paths to validate
connectivity via L7 proxies, in the following dimensions:

- Apply policy on egress; ingress; or both (proxy-to-proxy)
- Intra-node / Multi-node
- Allow / Deny

Note that proxy-to-proxy always configures egress allow policy to ensure
that the traffic goes via the proxy and in the drop case the requests
are only rejected at the destination. This is because applying egress
deny at the source would prevent proxy-to-proxy connectivity, meaning
the test would be equivalent to the egress-only reject policy case. This
way, we ensure that the path via the egress proxy to the destination is
tested in the reject case.

These are implemented partially through a new 'echo-c' pod which always
has ingress policy applied to allow GET requests to '/public'. Depending
on whether ingress policy is needed to check the particular permutation
the new checks may connect to 'echo-a' or 'echo-c'.

These are implemented by adding pods for each permutation of policy
apply point and topology; then by adding allow / deny containers within
that pod to test the allow/deny cases.

The 'connectivity-check-proxy.yaml' includes all of the above.

Finally, the omissions: This commit does not attempt to address
variations in datapath configuration. This includes IPv4 vs. IPv6;
tunnel/direct-routing; endpoint config; kube proxy/free; encryption.
These are left up to the cluster operator configuring Cilium in specific
modes and subsequently deploying these YAMLs.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Minor naming fixups

Make some of these resource names a bit more consistent.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Add quarantine label to metadata

This new label will be used during YAML generation to ensure that
resources which we are still working on fixes for are kept in a separate
category apart from the regular connectivity checks, to allow us to
check them in & distribute them without causing CI to instantly fail.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Add hostport + proxy checks

Introduces checks for egress proxy policy when accessing a hostport on a
remote node. These are added as part of the component=hostport-check to
ensure they are not pulled in when running connectivity checks in
environments without hostport support.

Additionally, these new tests are quarantined for now as they are known
to fail in some environments.

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Expand readme for latest checks

Signed-off-by: Joe Stringer <joe@cilium.io>

* connectivity-check: Re-add liveness probes

It appears that some of these checks require liveness probes rather than
readiness probes to pass on the github actions smoke-test, so ensure all
containers are checked with both.

Signed-off-by: Joe Stringer <joe@cilium.io>

* smoke-test: Improve state gathering upon failure

Commit bb91571 ("smoke-test: Print pod/deploy state on failure")
attempted to improve the information available during a failure from the
smoke-tests, but only added it to the quick-install test and not the
conformance test. Add the same output also to the conformance test so we
can more easily debug failures there.

Signed-off-by: Joe Stringer <joe@cilium.io>

* smoke-test: Disable bpf masquerading

In the smoke test, we are relying on kube-proxy for service connectivity
so it doesn't make sense to enable BPF masquerading. In fact, this
causes issues for connectivity from a node to a pod on a remote node via
ClusterIP (see related issue).

For the moment, disable BPF masquerading while we figure out the
longer-term solution to that issue.

Related: #12699

Signed-off-by: Joe Stringer <joe@cilium.io>

* docs: Update connectivity-check examples

Signed-off-by: Joe Stringer <joe@cilium.io>
  • Loading branch information
joestringer committed Jul 29, 2020
1 parent 3de518a commit 8a03d54
Show file tree
Hide file tree
Showing 38 changed files with 5,267 additions and 1,796 deletions.
21 changes: 5 additions & 16 deletions .github/workflows/smoke-test.yaml
Expand Up @@ -85,14 +85,7 @@ jobs:
run: |
kubectl get pods -o wide
kubectl get deploy -o wide
kubectl describe service echo-a
kubectl logs service/echo-a --all-containers --since=$LOG_TIME
kubectl describe service echo-b
kubectl logs service/echo-b --all-containers --since=$LOG_TIME
kubectl describe service echo-b-headless
kubectl logs service/echo-b-headless --all-containers --since=$LOG_TIME
kubectl describe service echo-b-host-headless
kubectl logs service/echo-b-host-headless --all-containers --since=$LOG_TIME
for svc in $(make -C examples/kubernetes/connectivity-check/ list | grep Service | awk '{ print $4 }'); do kubectl describe service $svc; kubectl logs service/$svc --all-containers --since=$LOG_TIME; done
- name: Dump hubble related logs and events
if: ${{ failure() && matrix.target.name == 'experimental-install' }}
Expand Down Expand Up @@ -139,6 +132,7 @@ jobs:
--set global.externalIPs.enabled=true \
--set global.nodePort.enabled=true \
--set global.hostPort.enabled=true \
--set config.bpfMasquerade=false \
--set config.ipam=kubernetes \
--set global.pullPolicy=Never
Expand All @@ -165,11 +159,6 @@ jobs:
env:
LOG_TIME: 30m
run: |
kubectl describe service echo-a
kubectl logs service/echo-a --all-containers --since=$LOG_TIME
kubectl describe service echo-b
kubectl logs service/echo-b --all-containers --since=$LOG_TIME
kubectl describe service echo-b-headless
kubectl logs service/echo-b-headless --all-containers --since=$LOG_TIME
kubectl describe service echo-b-host-headless
kubectl logs service/echo-b-host-headless --all-containers --since=$LOG_TIME
kubectl get pods -o wide
kubectl get deploy -o wide
for svc in $(make -C examples/kubernetes/connectivity-check/ list | grep Service | awk '{ print $4 }'); do kubectl describe service $svc; kubectl logs service/$svc --all-containers --since=$LOG_TIME; done
33 changes: 16 additions & 17 deletions Documentation/gettingstarted/k8s-install-connectivity-test.rst
Expand Up @@ -13,23 +13,22 @@ service load-balancing and various network policy combinations. The pod name
indicates the connectivity variant and the readiness and liveness gate
indicates success or failure of the test:

.. code:: bash
NAME READY STATUS RESTARTS AGE
echo-a-5995597649-f5d5g 1/1 Running 0 4m51s
echo-b-54c9bb5f5c-p6lxf 1/1 Running 0 4m50s
echo-b-host-67446447f7-chvsp 1/1 Running 0 4m50s
host-to-b-multi-node-clusterip-78f9869d75-l8cf8 1/1 Running 0 4m50s
host-to-b-multi-node-headless-798949bd5f-vvfff 1/1 Running 0 4m50s
pod-to-a-59b5fcb7f6-gq4hd 1/1 Running 0 4m50s
pod-to-a-allowed-cnp-55f885bf8b-5lxzz 1/1 Running 0 4m50s
pod-to-a-external-1111-7ff666fd8-v5kqb 1/1 Running 0 4m48s
pod-to-a-l3-denied-cnp-64c6c75c5d-xmqhw 1/1 Running 0 4m50s
pod-to-b-intra-node-845f955cdc-5nfrt 1/1 Running 0 4m49s
pod-to-b-multi-node-clusterip-666594b445-bsn4j 1/1 Running 0 4m49s
pod-to-b-multi-node-headless-746f84dff5-prk4w 1/1 Running 0 4m49s
pod-to-b-multi-node-nodeport-7cb9c6cb8b-ksm4h 1/1 Running 0 4m49s
pod-to-external-fqdn-allow-google-cnp-b7b6bcdcb-tg9dh 1/1 Running 0 4m48s
.. code:: shell-session
$ kubectl get pods -n cilium-test
NAME READY STATUS RESTARTS AGE
echo-a-6788c799fd-42qxx 1/1 Running 0 69s
echo-b-59757679d4-pjtdl 1/1 Running 0 69s
echo-b-host-f86bd784d-wnh4v 1/1 Running 0 68s
host-to-b-multi-node-clusterip-585db65b4d-x74nz 1/1 Running 0 68s
host-to-b-multi-node-headless-77c64bc7d8-kgf8p 1/1 Running 0 67s
pod-to-a-allowed-cnp-87b5895c8-bfw4x 1/1 Running 0 68s
pod-to-a-b76ddb6b4-2v4kb 1/1 Running 0 68s
pod-to-a-denied-cnp-677d9f567b-kkjp4 1/1 Running 0 68s
pod-to-b-multi-node-clusterip-f7655dbc8-h5bwk 1/1 Running 0 68s
pod-to-b-multi-node-headless-5fd98b9648-5bjj8 1/1 Running 0 68s
pod-to-external-1111-7489c7c46d-jhtkr 1/1 Running 0 68s
pod-to-external-fqdn-allow-google-cnp-b7b6bcdcb-97p75 1/1 Running 0 68s
.. note::

Expand Down
20 changes: 1 addition & 19 deletions Documentation/gettingstarted/kube-router.rst
Expand Up @@ -137,22 +137,4 @@ installed:
* ``10.2.2.0/24 dev tun-172011760 proto 17 src 172.0.50.227``
* ``10.2.3.0/24 dev tun-1720186231 proto 17 src 172.0.50.227``

You can test connectivity by deploying the following connectivity checker pods:

.. parsed-literal::
$ kubectl create -f \ |SCM_WEB|\/examples/kubernetes/connectivity-check/connectivity-check.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
echo-a-dd67f6b4b-s62jl 1/1 Running 0 2m15s
echo-b-55d8dbd74f-t8jwk 1/1 Running 0 2m15s
host-to-b-multi-node-clusterip-686f99995d-tn6kq 1/1 Running 0 2m15s
host-to-b-multi-node-headless-bdbc856d-9zv4x 1/1 Running 0 2m15s
pod-to-a-766584ffff-wh2s8 1/1 Running 0 2m15s
pod-to-a-allowed-cnp-5899c44899-f9tdv 1/1 Running 0 2m15s
pod-to-a-external-1111-55c488465-7sd55 1/1 Running 0 2m14s
pod-to-a-l3-denied-cnp-856998c977-j9dhs 1/1 Running 0 2m15s
pod-to-b-intra-node-7b6cbc6c56-hqz7r 1/1 Running 0 2m15s
pod-to-b-multi-node-clusterip-77c8446b6d-qc8ch 1/1 Running 0 2m15s
pod-to-b-multi-node-headless-854b65674d-9zlp8 1/1 Running 0 2m15s
pod-to-external-fqdn-allow-google-cnp-bb9597947-bc85q 1/1 Running 0 2m14s
.. include:: k8s-install-connectivity-test.rst
31 changes: 16 additions & 15 deletions Documentation/troubleshooting.rst
Expand Up @@ -357,22 +357,23 @@ test:

.. _test: \ |SCM_WEB|\/examples/kubernetes/connectivity-check/connectivity-check.yaml

.. code:: bash
.. code:: shell-session
$ kubectl get pods -n cilium-test
NAME READY STATUS RESTARTS AGE
echo-a-6788c799fd-42qxx 1/1 Running 0 69s
echo-b-59757679d4-pjtdl 1/1 Running 0 69s
echo-b-host-f86bd784d-wnh4v 1/1 Running 0 68s
host-to-b-multi-node-clusterip-585db65b4d-x74nz 1/1 Running 0 68s
host-to-b-multi-node-headless-77c64bc7d8-kgf8p 1/1 Running 0 67s
pod-to-a-allowed-cnp-87b5895c8-bfw4x 1/1 Running 0 68s
pod-to-a-b76ddb6b4-2v4kb 1/1 Running 0 68s
pod-to-a-denied-cnp-677d9f567b-kkjp4 1/1 Running 0 68s
pod-to-b-multi-node-clusterip-f7655dbc8-h5bwk 1/1 Running 0 68s
pod-to-b-multi-node-headless-5fd98b9648-5bjj8 1/1 Running 0 68s
pod-to-external-1111-7489c7c46d-jhtkr 1/1 Running 0 68s
pod-to-external-fqdn-allow-google-cnp-b7b6bcdcb-97p75 1/1 Running 0 68s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
echo-a-9b85dd869-292s2 1/1 Running 0 8m37s
echo-b-c7d9f4686-gdwcs 1/1 Running 0 8m37s
host-to-b-multi-node-clusterip-6d496f7cf9-956jb 1/1 Running 0 8m37s
host-to-b-multi-node-headless-bd589bbcf-jwbh2 1/1 Running 0 8m37s
pod-to-a-7cc4b6c5b8-9jfjb 1/1 Running 0 8m36s
pod-to-a-allowed-cnp-6cc776bb4d-2cszk 1/1 Running 0 8m36s
pod-to-a-external-1111-5c75bd66db-sxfck 1/1 Running 0 8m35s
pod-to-a-l3-denied-cnp-7fdd9975dd-2pp96 1/1 Running 0 8m36s
pod-to-b-intra-node-9d9d4d6f9-qccfs 1/1 Running 0 8m35s
pod-to-b-multi-node-clusterip-5956c84b7c-hwzfg 1/1 Running 0 8m35s
pod-to-b-multi-node-headless-6698899447-xlhfw 1/1 Running 0 8m35s
pod-to-external-fqdn-allow-google-cnp-667649bbf6-v6rf8 1/1 Running 0 8m35s
Information about test failures can be determined by describing a failed test
pod
Expand Down
95 changes: 75 additions & 20 deletions examples/kubernetes/connectivity-check/Makefile
@@ -1,35 +1,90 @@
# Copyright 2017-2020 Authors of Cilium
# SPDX-License-Identifier: Apache-2.0
#

include ../../../Makefile.defs
include ../../../Makefile.quiet

DEFAULT_OUT := connectivity-check.yaml
HOSTPORT_OUT := connectivity-check-hostport.yaml
SINGLE_OUT := connectivity-check-single-node.yaml
PROXY_OUT := connectivity-check-proxy.yaml
QUARANTINE_OUT := connectivity-check-quarantine.yaml

SERVERS_NAME := echo-a echo-b echo-b-host echo-b-host-headless echo-c echo-c-host echo-c-host-headless
SERVERS_OUT := servers.yaml

SRC := $(wildcard *.yaml)
HOSTPORT_SRC := $(filter-out $(DEFAULT_OUT) $(HOSTPORT_OUT) $(SINGLE_OUT), $(SRC))
DEFAULT_SRC := $(filter-out $(wildcard *-hostport.yaml),$(HOSTPORT_SRC))
SINGLE_SRC := $(filter-out $(wildcard *-multi-node*.yaml),$(DEFAULT_SRC))
SRC := $(wildcard *.cue)
ALL_TARGETS := $(DEFAULT_OUT) $(HOSTPORT_OUT) $(SINGLE_OUT) $(PROXY_OUT) $(QUARANTINE_OUT)

DOCKER_RUN := $(CONTAINER_ENGINE) container run --rm \
--workdir /src/examples/kubernetes/connectivity-check \
--volume $(CURDIR)/../../..:/src \
--user "$(shell id -u):$(shell id -g)"

all: $(DEFAULT_OUT) $(HOSTPORT_OUT) $(SINGLE_OUT)
CUE_IMAGE := "docker.io/cuelang/cue:v0.2.2@sha256:2ea932c771212db140c9996c6fff1d236f3f84ae82add914374cee553b6fc60c"
CUE := $(DOCKER_RUN) $(CUE_IMAGE)

$(DEFAULT_OUT): $(DEFAULT_SRC)
all: $(ALL_TARGETS)

$(DEFAULT_OUT): $(SRC)
@echo '# Automatically generated by Makefile. DO NOT EDIT' > $(DEFAULT_OUT)
for FILE in $(DEFAULT_SRC); do \
cat $$FILE >> $(DEFAULT_OUT); \
echo "---" >> $(DEFAULT_OUT); \
done
$(QUIET)$(CUE) dump > $(DEFAULT_OUT)

$(HOSTPORT_OUT): $(HOSTPORT_SRC)
$(HOSTPORT_OUT): $(SRC)
@echo '# Automatically generated by Makefile. DO NOT EDIT' > $(HOSTPORT_OUT)
for FILE in $(HOSTPORT_SRC); do \
cat $$FILE >> $(HOSTPORT_OUT); \
echo "---" >> $(HOSTPORT_OUT); \
done
$(QUIET)$(CUE) -t component=all dump > $(HOSTPORT_OUT)

$(SINGLE_OUT): $(SINGLE_SRC)
$(SINGLE_OUT): $(SRC)
@echo '# Automatically generated by Makefile. DO NOT EDIT' > $(SINGLE_OUT)
for FILE in $(SINGLE_SRC); do \
cat $$FILE >> $(SINGLE_OUT); \
echo "---" >> $(SINGLE_OUT); \
$(QUIET)$(CUE) -t topology=single-node dump > $(SINGLE_OUT)

$(PROXY_OUT): $(SRC) $(SERVERS_OUT)
@echo '# Automatically generated by Makefile. DO NOT EDIT' > $(PROXY_OUT)
$(QUIET)$(CUE) -t component=proxy dump > $@
@cat $(SERVERS_OUT) >> $@

$(QUARANTINE_OUT): $(SRC) $(SERVERS_OUT)
@echo '# Automatically generated by Makefile. DO NOT EDIT' > $(QUARANTINE_OUT)
$(QUIET)$(CUE) -t component=all -t quarantine=true dump > $@
@cat $(SERVERS_OUT) >> $@

clean:
@rm -f $(ALL_TARGETS)
@rm -f *.new
@rm -f *.diff
@rm -f *.yaml

deploy:
$(QUIET)kubectl apply -f connectivity-check-hostport.yaml

eval:
$(QUIET)$(CUE) eval -c ./...

# To easier inspect individual yamls for specific checks, generate all YAMLs from *.cue
generate_all: $(SRC)
# TODO: Don't run docker for every command
@for deployment in $(shell $(CUE) -t component=all ls | tail -n+2 | awk '{ print $$4 }' | sort | uniq); do \
$(CUE) -t component=all -t name=$$deployment dump > $$deployment.yaml; \
done

inspect:
@echo "Comparing latest cue declarations against cluster deployment from "make deploy"..."
$(QUIET)$(CUE) -t component=all dump > connectivity-check-hostport.yaml.new
-@kubectl diff -f connectivity-check-hostport.yaml.new > connectivity-check-hostport.yaml.diff
@cat connectivity-check-hostport.yaml.diff
@echo
@echo "The full diff is available in connectivity-check-hostport.yaml.diff."

help:
$(QUIET)$(CUE) cmd help

list:
$(QUIET)$(CUE) cmd ls

$(SERVERS_OUT): $(SRC)
@echo > $(SERVERS_OUT)
@for name in $(SERVERS_NAME); do \
$(CUE) cmd -t name=$$name dump >> $@; \
done

.PHONY: all clean deploy eval generate_all help inspect list
32 changes: 32 additions & 0 deletions examples/kubernetes/connectivity-check/README.md
Expand Up @@ -2,3 +2,35 @@

Set of deployments that will perform a series of connectivity checks via
liveness and readiness checks. An unhealthy/unready pod indicates a problem.

## Connectivity checks

* [Standard connectivity checks](./connectivity-check.yaml)
* [Standard connectivity checks with hostport](./connectivity-check-hostport.yaml)
* Requires either eBPF hostport to be enabled or portmap CNI chaining.
* [Single-node connectivity checks](./connectivity-check-single-node.yaml)
* Standard connectivity checks minus the checks that require multiple nodes.
* [Proxy connectivity checks](./connectivity-check-proxy.yaml)
* Extra checks for various paths involving Layer 7 policy.

## Developer documentation

These checks are written in [CUE](https://cuelang.org/) to define various
checks in a concise manner. The definitions for the checks are split across
multiple files per the following logic:

* `resources.cue`: The main definitions for templating all Kubernetes resources
including Deployment, Service, and CiliumNetworkPolicy.
* `echo-servers.cue`: Data definitions for all `echo-*` servers used for other
connectivity checks.
* `defaults.cue`: Default parameters used to define how specific checks connect
to particular echo servers, including selecting the probe destination,
selecting pod affinity, and default image for all checks.
* `network.cue`, `policy.cue`, `proxy.cue`, `services.cue`: Data definitions
for various connectivity checks at different layers and using different
features. L7 policy checks are defined in `proxy.cue` and not `policy.cue`.
* `*_tool.cue`: Various CLI tools for listing and generating the YAML
definitons used above. For more information, run `make help` in this
directory.

For more information, see https://github.com/cilium/cilium/pull/12599 .

0 comments on commit 8a03d54

Please sign in to comment.