【Kubernetes in Action读书笔记】4.3 使用ReplicaSet
据说ReplicationController最终将被弃用,所以跳过4.2节。
ReplicaSet能够保障所管理的Pod的数量总是与预期的数量一致。
相较于ReplicationController,ReplicaSet的Pod选择器的表达能力更强。
ReplicaSet的yaml的示例
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
matchExpressions:
- key: env,
operator: In,
values:
- prod
- qa
...
选择器selector相关代码
相关文件
- staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go
- staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers.go
- staging/src/k8s.io/apimachinery/pkg/labels/selector.go
yaml文件中的配置项spec.selector.matchLabels和spec.selector.matchExpressions对应的类型
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go
// A label selector is a label query over a set of resources.
type LabelSelector struct {
// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
// map is equivalent to an element of matchExpressions, whose key field is "key", the
// operator is "In", and the values array contains only "value". The requirements are ANDed.
MatchLabels map[string]string
// matchExpressions is a list of label selector requirements. The requirements are ANDed.
MatchExpressions []LabelSelectorRequirement
}
// A label selector requirement is a selector that contains values, a key, and an operator that
// relates the key and values.
type LabelSelectorRequirement struct {
Key string
// operator represents a key's relationship to a set of values.
// Valid operators are In, NotIn, Exists and DoesNotExist.
Operator LabelSelectorOperator
Values []string
}
// A label selector operator is the set of operators that can be used in a selector requirement.
type LabelSelectorOperator string
每一个选择器(selector中的元素)都对应一个Requirement类型的值
// staging/src/k8s.io/apimachinery/pkg/labels/selector.go
// Requirements is AND of all requirements.
type Requirements []Requirement
// Selector represents a label selector.
type Selector interface {
...
LabelSelectorAsSelector()将LabelSelector类型转换为实现了接口labels.Selector的类型——type internalSelector []Requirement——一组Requirement
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers.go
// LabelSelectorAsSelector converts the LabelSelector api type into a struct that implements
// labels.Selector
// ...
func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
// ...
for k, v := range ps.MatchLabels {
r, err := labels.NewRequirement(k, selection.Equals, []string{v}) // ①
// ...
requirements = append(requirements, *r)
}
for _, expr := range ps.MatchExpressions {
// ...
r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...))//②
// ...
requirements = append(requirements, *r)
}
selector := labels.NewSelector() // ③
selector = selector.Add(requirements...)
return selector, nil
}
// ...
// Add adds requirements to the selector. It copies the current selector returning a new one
func (s internalSelector) Add(reqs ...Requirement) Selector {
ret := make(internalSelector, 0, len(s)+len(reqs))
ret = append(ret, s...)
ret = append(ret, reqs...)
sort.Sort(ByKey(ret))
return ret
}
-
① 将
spec.selector.matchLabels配置项中的元素一一转换成*labels.Requirement -
② 将
spec.selector.matchExpressions配置项中的元素也一一转换成*labels.Requirement -
③ 创建实现了接口
labels.Selector的类型internalSelector的变量selector。该类型实际上是[]Requirement的别名
检测Requirement是否匹配给定的标签lable
// staging/src/k8s.io/apimachinery/pkg/labels/selector.go
func (s internalSelector) Matches(l Labels) bool {
for ix := range s {
if matches := s[ix].Matches(l); !matches {
return false
}
}
return true
}
func (r *Requirement) Matches(ls Labels) bool {
switch r.operator {
case selection.In, selection.Equals, selection.DoubleEquals:
// ...
case selection.NotIn, selection.NotEquals:
// ...
case selection.Exists:
// ...
直接通过switch case处理,不是用Requirement的“子类”,用多态的Matches()方法。
待确认:这里
Labels是复数,但从注释里看Labels似乎又代表1个标签// Labels allows you to present labels independently from their storage. type Labels interface { // Has returns whether the provided label exists. Has(label string) (exists bool) // Get returns the value for the provided label. Get(label string) (value string) }会不会名词复数是一种接口命名风格
nothingSelector与Rust中的基元型结构体
另外,nothingSelector类似Rust中的基元型结构体(Unit-like structs)。
// staging/src/k8s.io/apimachinery/pkg/labels/selector.go
type nothingSelector struct{}
func (n nothingSelector) Matches(_ Labels) bool { return false }
func (n nothingSelector) Empty() bool { return false }
func (n nothingSelector) String() string { return "" }
func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
// ...
// Sharing this saves 1 alloc per use; this is safe because it's immutable.
var sharedNothingSelector Selector = nothingSelector{}
似乎即使每次使用时都在堆上(无论用new还是&)创建了“新的”nothingSelector的值,Go也只会在内存中存储一份该类型的值。
type nothingSelector struct{}
func main() {
fmt.Printf("%p\n", new(nothingSelector)) // 0x54e3a0
fmt.Printf("%p\n", new(nothingSelector)) // 0x54e3a0
fmt.Printf("%p\n", ¬hingSelector{}) // 0x54e3a0
}
4.3节翻译错误的地方
P104 4.3节 第1段
最初,ReplicationController是用于复制和在异常时重新调度节点的唯一Kubernetes组件,……
Initially, ReplicationControllers were the only Kubernetes component for replicating pods and rescheduling them when nodes failed.
“复制”和“重新调度”的对象都是Pod