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 })