github.com/zhyoulun/cilium@v1.6.12/test/k8sT/fqdn.go (about)

     1  // Copyright 2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package k8sTest
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  
    21  	. "github.com/cilium/cilium/test/ginkgo-ext"
    22  	"github.com/cilium/cilium/test/helpers"
    23  
    24  	. "github.com/onsi/gomega"
    25  )
    26  
    27  var _ = Describe("K8sFQDNTest", func() {
    28  	var (
    29  		kubectl          *helpers.Kubectl
    30  		microscopeErr    error
    31  		microscopeCancel                    = func() error { return nil }
    32  		backgroundCancel context.CancelFunc = func() { return }
    33  		backgroundError  error
    34  
    35  		bindManifest = helpers.ManifestGet("bind_deployment.yaml")
    36  		demoManifest = helpers.ManifestGet("demo.yaml")
    37  
    38  		apps    = []string{helpers.App2, helpers.App3}
    39  		appPods map[string]string
    40  
    41  		worldTarget          = "http://world1.cilium.test"
    42  		worldTargetIP        = "192.168.9.10"
    43  		worldInvalidTarget   = "http://world2.cilium.test"
    44  		worldInvalidTargetIP = "192.168.9.11"
    45  	)
    46  
    47  	BeforeAll(func() {
    48  		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
    49  		DeployCiliumAndDNS(kubectl)
    50  
    51  		By("Applying bind deployment")
    52  		bindManifest = helpers.ManifestGet("bind_deployment.yaml")
    53  
    54  		res := kubectl.ApplyDefault(bindManifest)
    55  		res.ExpectSuccess("Bind config cannot be deployed")
    56  
    57  		By("Applying demo manifest")
    58  		res = kubectl.ApplyDefault(demoManifest)
    59  		res.ExpectSuccess("Demo config cannot be deployed")
    60  
    61  		err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", helpers.HelperTimeout)
    62  		Expect(err).Should(BeNil(), "Testapp is not ready after timeout")
    63  
    64  		appPods = helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "id")
    65  	})
    66  
    67  	AfterFailed(func() {
    68  		kubectl.CiliumReport(helpers.KubeSystemNamespace,
    69  			"cilium service list",
    70  			"cilium endpoint list")
    71  	})
    72  
    73  	AfterAll(func() {
    74  		_ = kubectl.Delete(bindManifest)
    75  		_ = kubectl.Delete(demoManifest)
    76  		ExpectAllPodsTerminated(kubectl)
    77  		kubectl.CloseSSHClient()
    78  	})
    79  
    80  	JustBeforeEach(func() {
    81  		microscopeErr, microscopeCancel = kubectl.MicroscopeStart()
    82  		Expect(microscopeErr).To(BeNil(), "Microscope cannot be started")
    83  		backgroundCancel, backgroundError = kubectl.BackgroundReport("uptime")
    84  		Expect(backgroundError).To(BeNil(), "Cannot start background report process")
    85  	})
    86  
    87  	JustAfterEach(func() {
    88  		kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
    89  		Expect(microscopeCancel()).To(BeNil(), "cannot stop microscope")
    90  		backgroundCancel()
    91  	})
    92  
    93  	AfterEach(func() {
    94  		_ = kubectl.Exec(fmt.Sprintf("%s delete --all cnp", helpers.KubectlCmd))
    95  	})
    96  
    97  	It("Restart Cilium validate that FQDN is still working", func() {
    98  		// Test functionality:
    99  		// - When Cilium is running) Connectivity from App2 application can
   100  		// connect to DNS because dns-proxy filter the DNS request. If the
   101  		// connection is made correctly the IP is whitelisted by the FQDN rule
   102  		// until the DNS TTL expires.
   103  		// When Cilium is not running) The DNS-proxy is not working, so the IP
   104  		// connectivity to an existing IP that was queried before will work,
   105  		// meanwhile connections using new DNS request will fail.
   106  		// On restart) Cilium will restore the IPS that were white-listted in
   107  		// the FQDN and connection will work as normal.
   108  
   109  		connectivityTest := func() {
   110  
   111  			By("Testing that connection from %q to %q should work",
   112  				appPods[helpers.App2], worldTarget)
   113  			res := kubectl.ExecPodCmd(
   114  				helpers.DefaultNamespace, appPods[helpers.App2],
   115  				helpers.CurlFail(worldTarget))
   116  			ExpectWithOffset(1, res).To(helpers.CMDSuccess(), "%q cannot curl to %q",
   117  				appPods[helpers.App2], worldTarget)
   118  
   119  			By("Testing that connection from %q to %q shouldn't work",
   120  				appPods[helpers.App2], worldTarget)
   121  			res = kubectl.ExecPodCmd(
   122  				helpers.DefaultNamespace, appPods[helpers.App2],
   123  				helpers.CurlFail(worldInvalidTarget))
   124  			ExpectWithOffset(1, res).ShouldNot(helpers.CMDSuccess(),
   125  				"%q can curl to %q when it should fail", appPods[helpers.App2], worldInvalidTarget)
   126  
   127  			By("Testing that connection from %q to %q works",
   128  				appPods[helpers.App2], worldInvalidTarget)
   129  			res = kubectl.ExecPodCmd(
   130  				helpers.DefaultNamespace, appPods[helpers.App2],
   131  				helpers.CurlFail(worldTargetIP))
   132  			res.ExpectSuccess("%q cannot curl to %q during restart", helpers.App2, worldTargetIP)
   133  
   134  			By("Testing that connection from %q to %q should not work",
   135  				appPods[helpers.App2], worldInvalidTargetIP)
   136  			res = kubectl.ExecPodCmd(
   137  				helpers.DefaultNamespace, appPods[helpers.App2],
   138  				helpers.CurlFail(worldInvalidTargetIP))
   139  			res.ExpectFail("%q can  connect when it should not work", helpers.App2)
   140  		}
   141  
   142  		fqndProxyPolicy := helpers.ManifestGet("fqdn-proxy-policy.yaml")
   143  
   144  		_, err := kubectl.CiliumPolicyAction(
   145  			helpers.DefaultNamespace, fqndProxyPolicy,
   146  			helpers.KubectlApply, helpers.HelperTimeout)
   147  		Expect(err).To(BeNil(), "Cannot install fqdn proxy policy")
   148  
   149  		connectivityTest()
   150  		By("Deleting cilium pods")
   151  
   152  		res := kubectl.Exec(fmt.Sprintf("%s -n %s delete pods -l k8s-app=cilium",
   153  			helpers.KubectlCmd, helpers.KubeSystemNamespace))
   154  		res.ExpectSuccess()
   155  
   156  		By("Testing connectivity when cilium is restoring using IPS without DNS")
   157  		res = kubectl.ExecPodCmd(
   158  			helpers.DefaultNamespace, appPods[helpers.App2],
   159  			helpers.CurlFail(worldTargetIP))
   160  		res.ExpectSuccess("%q cannot curl to %q during restart", helpers.App2, worldTargetIP)
   161  
   162  		res = kubectl.ExecPodCmd(
   163  			helpers.DefaultNamespace, appPods[helpers.App2],
   164  			helpers.CurlFail(worldInvalidTargetIP))
   165  		res.ExpectFail("%q can  connect when it should not work", helpers.App2)
   166  
   167  		ExpectAllPodsTerminated(kubectl)
   168  		ExpectCiliumReady(kubectl)
   169  
   170  		// @TODO This endpoint ready call SHOULD NOT be here
   171  		// Here some packets can be lost due to two different scenarios:
   172  		//
   173  		// 1) On restore the endpoint/fqdn policies, the identity ID for the
   174  		// CIDRSet can be different, so if one endpoint start to regenerate and
   175  		// other still have the old identity things can mess around and some
   176  		// IPs are not white listed correctly. To prevent this, a restore for
   177  		// local-identities will be added in the future.
   178  		//
   179  		// 2) On restore, the Kubernetes watcher is sending the CNP back to
   180  		// Cilium, and before the endoint is restored the CNP can be applied
   181  		// without the ToCIDRSet, this means that there is no TOCIDR rule in
   182  		// the cilium policy and traffic will be drop.
   183  
   184  		// As mentioned above, these endpoints ready should not be there, the only
   185  		// reason to have this piece of code here is to reduce a flaky test.
   186  		err = kubectl.CiliumEndpointWaitReady()
   187  		Expect(err).To(BeNil(), "Endpoints are not ready after Cilium restarts")
   188  
   189  		By("Testing connectivity when cilium is *restored* using IPS without DNS")
   190  		res = kubectl.ExecPodCmd(
   191  			helpers.DefaultNamespace, appPods[helpers.App2],
   192  			helpers.CurlFail(worldTargetIP))
   193  		res.ExpectSuccess("%q cannot curl to %q after restart", helpers.App2, worldTargetIP)
   194  
   195  		res = kubectl.ExecPodCmd(
   196  			helpers.DefaultNamespace, appPods[helpers.App2],
   197  			helpers.CurlFail(worldInvalidTargetIP))
   198  		res.ExpectFail("%q can  connect when it should not work", helpers.App2)
   199  
   200  		By("Testing connectivity using DNS request when cilium is restored correctly")
   201  		connectivityTest()
   202  	})
   203  
   204  	It("Validate that multiple specs are working correctly", func() {
   205  		// To make sure that UUID in multiple specs are plumbed correctly to
   206  		// Cilium Policy
   207  		fqdnPolicy := helpers.ManifestGet("fqdn-proxy-multiple-specs.yaml")
   208  		world1Target := "http://world1.cilium.test"
   209  		world2Target := "http://world2.cilium.test"
   210  
   211  		_, err := kubectl.CiliumPolicyAction(
   212  			helpers.DefaultNamespace, fqdnPolicy,
   213  			helpers.KubectlApply, helpers.HelperTimeout)
   214  		Expect(err).To(BeNil(), "Cannot install fqdn proxy policy")
   215  
   216  		By("Validating APP2 policy connectivity")
   217  		res := kubectl.ExecPodCmd(
   218  			helpers.DefaultNamespace, appPods[helpers.App2],
   219  			helpers.CurlFail(world1Target))
   220  		res.ExpectSuccess("Can't connect to to a valid target when it should work")
   221  
   222  		res = kubectl.ExecPodCmd(
   223  			helpers.DefaultNamespace, appPods[helpers.App2],
   224  			helpers.CurlFail(world2Target))
   225  		res.ExpectFail("Can connect to a valid target when it should NOT work")
   226  
   227  		By("Validating APP3 policy connectivity")
   228  
   229  		res = kubectl.ExecPodCmd(
   230  			helpers.DefaultNamespace, appPods[helpers.App3],
   231  			helpers.CurlFail(world2Target))
   232  		res.ExpectSuccess("Can't connect to to a valid target when it should work")
   233  
   234  		res = kubectl.ExecPodCmd(
   235  			helpers.DefaultNamespace, appPods[helpers.App3],
   236  			helpers.CurlFail(world1Target))
   237  		res.ExpectFail("Can connect to to a valid target when it should NOT work")
   238  	})
   239  })