ipvs.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package ipvs
  14. import (
  15. "net"
  16. "strconv"
  17. "strings"
  18. "fmt"
  19. "k8s.io/apimachinery/pkg/util/version"
  20. "k8s.io/utils/exec"
  21. )
  22. // Interface is an injectable interface for running ipvs commands. Implementations must be goroutine-safe.
  23. type Interface interface {
  24. // Flush clears all virtual servers in system. return occurred error immediately.
  25. Flush() error
  26. // AddVirtualServer creates the specified virtual server.
  27. AddVirtualServer(*VirtualServer) error
  28. // UpdateVirtualServer updates an already existing virtual server. If the virtual server does not exist, return error.
  29. UpdateVirtualServer(*VirtualServer) error
  30. // DeleteVirtualServer deletes the specified virtual server. If the virtual server does not exist, return error.
  31. DeleteVirtualServer(*VirtualServer) error
  32. // Given a partial virtual server, GetVirtualServer will return the specified virtual server information in the system.
  33. GetVirtualServer(*VirtualServer) (*VirtualServer, error)
  34. // GetVirtualServers lists all virtual servers in the system.
  35. GetVirtualServers() ([]*VirtualServer, error)
  36. // AddRealServer creates the specified real server for the specified virtual server.
  37. AddRealServer(*VirtualServer, *RealServer) error
  38. // GetRealServers returns all real servers for the specified virtual server.
  39. GetRealServers(*VirtualServer) ([]*RealServer, error)
  40. // DeleteRealServer deletes the specified real server from the specified virtual server.
  41. DeleteRealServer(*VirtualServer, *RealServer) error
  42. // UpdateRealServer updates the specified real server from the specified virtual server.
  43. UpdateRealServer(*VirtualServer, *RealServer) error
  44. }
  45. // VirtualServer is an user-oriented definition of an IPVS virtual server in its entirety.
  46. type VirtualServer struct {
  47. Address net.IP
  48. Protocol string
  49. Port uint16
  50. Scheduler string
  51. Flags ServiceFlags
  52. Timeout uint32
  53. }
  54. // ServiceFlags is used to specify session affinity, ip hash etc.
  55. type ServiceFlags uint32
  56. const (
  57. // FlagPersistent specify IPVS service session affinity
  58. FlagPersistent = 0x1
  59. // FlagHashed specify IPVS service hash flag
  60. FlagHashed = 0x2
  61. // IPVSProxyMode is match set up cluster with ipvs proxy model
  62. IPVSProxyMode = "ipvs"
  63. )
  64. // IPVS required kernel modules.
  65. const (
  66. // ModIPVS is the kernel module "ip_vs"
  67. ModIPVS string = "ip_vs"
  68. // ModIPVSRR is the kernel module "ip_vs_rr"
  69. ModIPVSRR string = "ip_vs_rr"
  70. // ModIPVSWRR is the kernel module "ip_vs_wrr"
  71. ModIPVSWRR string = "ip_vs_wrr"
  72. // ModIPVSSH is the kernel module "ip_vs_sh"
  73. ModIPVSSH string = "ip_vs_sh"
  74. // ModNfConntrackIPV4 is the module "nf_conntrack_ipv4"
  75. ModNfConntrackIPV4 string = "nf_conntrack_ipv4"
  76. // ModNfConntrack is the kernel module "nf_conntrack"
  77. ModNfConntrack string = "nf_conntrack"
  78. )
  79. // Equal check the equality of virtual server.
  80. // We don't use struct == since it doesn't work because of slice.
  81. func (svc *VirtualServer) Equal(other *VirtualServer) bool {
  82. return svc.Address.Equal(other.Address) &&
  83. svc.Protocol == other.Protocol &&
  84. svc.Port == other.Port &&
  85. svc.Scheduler == other.Scheduler &&
  86. svc.Flags == other.Flags &&
  87. svc.Timeout == other.Timeout
  88. }
  89. func (svc *VirtualServer) String() string {
  90. return net.JoinHostPort(svc.Address.String(), strconv.Itoa(int(svc.Port))) + "/" + svc.Protocol
  91. }
  92. // RealServer is an user-oriented definition of an IPVS real server in its entirety.
  93. type RealServer struct {
  94. Address net.IP
  95. Port uint16
  96. Weight int
  97. ActiveConn int
  98. InactiveConn int
  99. }
  100. func (rs *RealServer) String() string {
  101. return net.JoinHostPort(rs.Address.String(), strconv.Itoa(int(rs.Port)))
  102. }
  103. // Equal check the equality of real server.
  104. // We don't use struct == since it doesn't work because of slice.
  105. func (rs *RealServer) Equal(other *RealServer) bool {
  106. return rs.Address.Equal(other.Address) &&
  107. rs.Port == other.Port
  108. }
  109. // GetKernelVersionAndIPVSMods returns the linux kernel version and the required ipvs modules
  110. func GetKernelVersionAndIPVSMods(Executor exec.Interface) (kernelVersion string, ipvsModules []string, err error) {
  111. kernelVersionFile := "/proc/sys/kernel/osrelease"
  112. out, err := Executor.Command("cut", "-f1", "-d", " ", kernelVersionFile).CombinedOutput()
  113. if err != nil {
  114. return "", nil, fmt.Errorf("error getting os release kernel version: %v(%s)", err, out)
  115. }
  116. kernelVersion = strings.TrimSpace(string(out))
  117. // parse kernel version
  118. ver1, err := version.ParseGeneric(kernelVersion)
  119. if err != nil {
  120. return kernelVersion, nil, fmt.Errorf("error parsing kernel version: %v(%s)", err, kernelVersion)
  121. }
  122. // "nf_conntrack_ipv4" has been removed since v4.19
  123. // see https://github.com/torvalds/linux/commit/a0ae2562c6c4b2721d9fddba63b7286c13517d9f
  124. ver2, _ := version.ParseGeneric("4.19")
  125. // get required ipvs modules
  126. if ver1.LessThan(ver2) {
  127. ipvsModules = append(ipvsModules, ModIPVS, ModIPVSRR, ModIPVSWRR, ModIPVSSH, ModNfConntrackIPV4)
  128. } else {
  129. ipvsModules = append(ipvsModules, ModIPVS, ModIPVSRR, ModIPVSWRR, ModIPVSSH, ModNfConntrack)
  130. }
  131. return kernelVersion, ipvsModules, nil
  132. }