helpers_windows.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // +build windows
  2. /*
  3. Copyright 2015 The Kubernetes Authors.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package dockershim
  15. import (
  16. "os"
  17. "github.com/blang/semver"
  18. dockertypes "github.com/docker/docker/api/types"
  19. dockercontainer "github.com/docker/docker/api/types/container"
  20. dockerfilters "github.com/docker/docker/api/types/filters"
  21. "k8s.io/klog"
  22. runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
  23. kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
  24. )
  25. func DefaultMemorySwap() int64 {
  26. return 0
  27. }
  28. func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) {
  29. if seccompProfile != "" {
  30. klog.Warningf("seccomp annotations are not supported on windows")
  31. }
  32. return nil, nil
  33. }
  34. // applyExperimentalCreateConfig applys experimental configures from sandbox annotations.
  35. func applyExperimentalCreateConfig(createConfig *dockertypes.ContainerCreateConfig, annotations map[string]string) {
  36. if kubeletapis.ShouldIsolatedByHyperV(annotations) {
  37. createConfig.HostConfig.Isolation = kubeletapis.HypervIsolationValue
  38. if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode == "" {
  39. createConfig.HostConfig.NetworkMode = dockercontainer.NetworkMode("none")
  40. }
  41. }
  42. }
  43. func (ds *dockerService) updateCreateConfig(
  44. createConfig *dockertypes.ContainerCreateConfig,
  45. config *runtimeapi.ContainerConfig,
  46. sandboxConfig *runtimeapi.PodSandboxConfig,
  47. podSandboxID string, securityOptSep rune, apiVersion *semver.Version) error {
  48. if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode != "" {
  49. createConfig.HostConfig.NetworkMode = dockercontainer.NetworkMode(networkMode)
  50. } else if !kubeletapis.ShouldIsolatedByHyperV(sandboxConfig.Annotations) {
  51. // Todo: Refactor this call in future for calling methods directly in security_context.go
  52. modifyHostOptionsForContainer(nil, podSandboxID, createConfig.HostConfig)
  53. }
  54. // Apply Windows-specific options if applicable.
  55. if wc := config.GetWindows(); wc != nil {
  56. rOpts := wc.GetResources()
  57. if rOpts != nil {
  58. createConfig.HostConfig.Resources = dockercontainer.Resources{
  59. Memory: rOpts.MemoryLimitInBytes,
  60. CPUShares: rOpts.CpuShares,
  61. CPUCount: rOpts.CpuCount,
  62. CPUPercent: rOpts.CpuMaximum,
  63. }
  64. }
  65. // Apply security context.
  66. applyWindowsContainerSecurityContext(wc.GetSecurityContext(), createConfig.Config, createConfig.HostConfig)
  67. }
  68. applyExperimentalCreateConfig(createConfig, sandboxConfig.Annotations)
  69. return nil
  70. }
  71. // applyWindowsContainerSecurityContext updates docker container options according to security context.
  72. func applyWindowsContainerSecurityContext(wsc *runtimeapi.WindowsContainerSecurityContext, config *dockercontainer.Config, hc *dockercontainer.HostConfig) {
  73. if wsc == nil {
  74. return
  75. }
  76. if wsc.GetRunAsUsername() != "" {
  77. config.User = wsc.GetRunAsUsername()
  78. }
  79. }
  80. func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) []string {
  81. opts := dockertypes.ContainerListOptions{
  82. All: true,
  83. Filters: dockerfilters.NewArgs(),
  84. }
  85. f := newDockerFilter(&opts.Filters)
  86. f.AddLabel(containerTypeLabelKey, containerTypeLabelContainer)
  87. f.AddLabel(sandboxIDLabelKey, sandboxID)
  88. containers, err := ds.client.ListContainers(opts)
  89. if err != nil {
  90. return nil
  91. }
  92. for _, c := range containers {
  93. r, err := ds.client.InspectContainer(c.ID)
  94. if err != nil {
  95. continue
  96. }
  97. // Versions and feature support
  98. // ============================
  99. // Windows version == Windows Server, Version 1709, Supports both sandbox and non-sandbox case
  100. // Windows version == Windows Server 2016 Support only non-sandbox case
  101. // Windows version < Windows Server 2016 is Not Supported
  102. // Sandbox support in Windows mandates CNI Plugin.
  103. // Presence of CONTAINER_NETWORK flag is considered as non-Sandbox cases here
  104. // Todo: Add a kernel version check for more validation
  105. if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode == "" {
  106. // On Windows, every container that is created in a Sandbox, needs to invoke CNI plugin again for adding the Network,
  107. // with the shared container name as NetNS info,
  108. // This is passed down to the platform to replicate some necessary information to the new container
  109. //
  110. // This place is chosen as a hack for now, since ds.getIP would end up calling CNI's addToNetwork
  111. // That is why addToNetwork is required to be idempotent
  112. // Instead of relying on this call, an explicit call to addToNetwork should be
  113. // done immediately after ContainerCreation, in case of Windows only. TBD Issue # to handle this
  114. if r.HostConfig.Isolation == kubeletapis.HypervIsolationValue {
  115. // Hyper-V only supports one container per Pod yet and the container will have a different
  116. // IP address from sandbox. Return the first non-sandbox container IP as POD IP.
  117. // TODO(feiskyer): remove this workaround after Hyper-V supports multiple containers per Pod.
  118. if containerIPs := ds.getIPs(c.ID, r); len(containerIPs) != 0 {
  119. return containerIPs
  120. }
  121. } else {
  122. // Do not return any IP, so that we would continue and get the IP of the Sandbox.
  123. // Windows 1709 and 1803 doesn't have the Namespace support, so getIP() is called
  124. // to replicate the DNS registry key to the Workload container (IP/Gateway/MAC is
  125. // set separately than DNS).
  126. // TODO(feiskyer): remove this workaround after Namespace is supported in Windows RS5.
  127. ds.getIPs(sandboxID, r)
  128. }
  129. } else {
  130. // ds.getIP will call the CNI plugin to fetch the IP
  131. if containerIPs := ds.getIPs(c.ID, r); len(containerIPs) != 0 {
  132. return containerIPs
  133. }
  134. }
  135. }
  136. return nil
  137. }
  138. func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) {
  139. // Currently in windows there is no identifier exposed for network namespace
  140. // Like docker, the referenced container id is used to figure out the network namespace id internally by the platform
  141. // so returning the docker networkMode (which holds container:<ref containerid> for network namespace here
  142. return string(c.HostConfig.NetworkMode), nil
  143. }